意
图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适
用 环
境
一个系统要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当你要强调一系列相关的产品对象的设计以便进行联合使用时。
当你提供一个产品类库,而只想显示它们的接口而不是实现时。
引言
在前一节,我们介绍了Strategy模式,并使用此模式实现了一个根据角色的职业来分配技能的范例(实际也就是动态地为类分配方法)。作为一款奇
幻RPG,有了职业,我们还应当可以为角色选择种族,比如说:人类(Human)、精灵(Elf)、矮人(Dwarf)、兽人(Orc)等等。而这四个种
族又有着截然不同的外形,精灵皮肤灰白、有着长长的耳朵、没有体毛和胡须;矮人的皮肤与人类近似,但是身材矮小、通常留着浓密的胡子;兽人则有着绿色的皮
肤和高大的身躯,并且面目丑陋。本文将讨论如何使用GOF的Abstract Factory抽象工厂来实现这样的角色外形设计。
面向实现的方式
简单起见,我们假设角色身体由三部分构成,分别是:头(Head)、身材(Stature)、皮肤(Skin)。那么对于人类的构造,我们的第一反
应自然而然地想到:它应当由
HumanHead、HumanStature、HumanSkin三个类复合而成。对于精灵也是类似的设计,于是,我们实现了下面这样的设计(本文将仅
以人类和精灵为例介绍):
抽象组成身体的实体类
我们发现这样做,每个角色与他的身体部件是牢牢绑定在一起的,每创建一个角色,我们都需要为它先行创建所有其复合的类(组成身体的实体类
(Concret
Class),比如HumanHead)。按照面向对象的思想,我们想到应该对这一过程进行封装,将创建角色部件这件事委派给其他的类来完成。观察上图,
我们发现尽管角色不同,但它们都是由三个部分构成,所以,我们所能想到的实现这一过程的第一步,就是对组成身体的实体类进行抽象,我们定义三个接
口:Head、Stature、Skin,代表身体的三个部分,并且让Human和Elf的实体类去实现这个接口:
观察上图,我们发现尽管定义了接口,但是如果角色Human和Elf仍然与接口的实体类关联,那么效果与面向实现完全相同。现在,是时候对设计做些
改动,我们让Human和Elf与接口关联,而不是与接口的实现关联(OO思想:面向接口编程,而不是面向实现编程)。这一次,我们的设计变成下图:
一眼望去,我们发现的第一个问题就是:Human与Elf惊人地相似,再仔细看看,我们注意到它们除了名字不同其余的完全一样。我们不禁思考:有必
要把两个完全一样的类起两个名字分别保存么?答案是没有必要,我们将它们合并成一个类,起名叫Race,设计再次变成下面这样:
创建工厂类
看到这里,我们可能会想:现在结构似乎已经很完善了,我们定义了接口来解决问题,也没有为不同的角色创建多个不同的类,而只要在Race的构造函数
中为代表身体部件的变量赋不同的值,就可以创建不同种族的角色。好的,那么我们来看看如果要创建一个Human 代码需要如何编写:
Head
head = new
HumanHead
();
Stature
stature = new
HumanStature
();
Skin
skin = new
HumanSkin
();
Race
human = new
Race
(head, stature, skin);
而Race的构造函数是这样的:
public
Race(head, stature, skin){
this
.head = head;
this
.stature = stature;
this
.skin = skin;
}
我们看到,仅仅创建一个类这样似乎太麻烦了,而且身体的部分类是角色的组成部分,为什么它们要先于角色创建呢?
这时候,我们想到如果有一个类可以专门负责创建身体部件这件事,当我们想要创建角色的时候,将这个类传递给Race的构造函数就可以了。我们管创建
Human身体组成部分的类称作:HumanPartsFactory,创建Elf身体部分的类称作ElfPartsFacotry。那么它们应该是这样
的:
现在,我们再要创建一个Human,代码变成了这样:
HumanPartsFactory
humanFactory = new
HumanPartsFactory
();
Race
Human = new
Race
(humanFactory);
相应的,我们的构造函数也需要改一改:
public
Race(HumanPartsFactory humanFacotry){
head = humanFactory.CreateHead();
stature = humanFactory.CreateStature();
skin = humanFactory.CreateSkin();
}
一切似乎都很好,直到我们需要创建一个Elf的时候...
我们发现Race的构造函数只能接受一个HumanPartsFactory类型的参数,为了传递ElfPartsFactory,我们将不得不再添加一
个接受ElfPartsFactory类型的构造函数。这样显然不好,这一次,有了之前的经验,我们知道我们可以通过同样的方法来解决。
看到这里,你是否能够体会到一些“面向接口”编程的意味?注意到RacePartsFactory,它内部的方法返回的都是接口类型,而其实体子类的方法返回的都是接口的实体类。如果我们之前不声明那看似无用的接口,这里是无法实现的。
现在,我们再次修改Race的构造函数:
public
Race(RacePartsFactory raceFacotry){
head = raceFacotry.CreateHead();
stature = raceFacotry.CreateStature();
skin = raceFacotry.CreateSkin();
}
当我们需要一个Human的时候:
RacePartsFactory
humanFactory = new
HumanPartsFactory
();
Race
human = new
Race
(humanFactory);
当我们需要一个Elf的时候:
RacePartsFactory
elfFactory = new
ElfPartsFactory
();
Race
elf = new
Race
(elfFactory);
Abstract Factory设计模式
上面做的这些,使我们又完成了一个设计模式:Abstract Factory。它的正式定义是这样的:提供一个接口用于创建一系列相互关联或者相互依赖的对象,而不需要指定它们的实体类。
下面是本例中 Abstract Factory模式的最终图:
代码实现和测试
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
AbstractFactory {
// 定义构成身体部分的接口
public
interface
IHead
{ string
name { get;} }
public
interface
IStature
{ string
name { get;} }
public
interface
ISkin
{ string
name { get;} }
// 组成 Human 的类
public
class
HumanHead
: IHead
{ public
string
name { get { return
"Human Head"
; } } }
public
class
HumanStature
: IStature
{ public
string
name { get { return
"Human Stature"
; } } }
public
class
HumanSkin
: ISkin
{ public
string
name { get { return
"Human Skin"
; } } }
// 组成 Elf 的类
public
class
ElfHead
: IHead
{ public
string
name { get { return
"Elf Head"
; } } }
public
class
ElfStature
: IStature
{ public
string
name { get { return
"Elf Stature"
; } } }
public
class
ElfSkin
: ISkin
{ public
string
name { get { return
"Elf Skin"
; } } }
// 定义工厂接口
public
interface
IRacePartsFactory
{
IHead CreateHead();
ISkin CreateSkin();
IStature CreateStature();
}
// 定义Human身体的工厂类
public
class
HumanPartsFactory
: IRacePartsFactory
{
public
IHead CreateHead() {
return
new
HumanHead();
}
public
IStature CreateStature() {
return
new
HumanStature();
}
public
ISkin CreateSkin() {
return
new
HumanSkin();
}
}
// 定义Elf身体的工厂类
public
class
ElfPartsFactory
: IRacePartsFactory
{
public
IHead CreateHead() {
return
new
ElfHead();
}
public
IStature CreateStature() {
return
new
ElfStature();
}
public
ISkin CreateSkin() {
return
new
ElfSkin();
}
}
// 定义 Race 类
public
class
Race
{
public
IHead
Head; // 做示范用,所以没有构建属性
public
IStature
Stature;
public
ISkin
Skin;
public
Race(IRacePartsFactory raceFactory) {
Head = raceFactory.CreateHead();
Stature = raceFactory.CreateStature();
Skin = raceFactory.CreateSkin();
}
}
class
Program
{
static
void
Main(string
[] args) {
// 创建一个 精灵(Elf)
Race
Elf = new
Race
(new
HumanPartsFactory());
Console
.WriteLine(Elf.Head.name);
Console
.WriteLine(Elf.Stature.name);
Console
.WriteLine(Elf.Skin.name);
}
}
}
总结
本文中我们一步步学习了Abstract Factory抽象工厂模式的实现。
我首先介绍了我们奇幻RPG所面临的一个问题:我们需要创建形态各异的角色。随后,我们通过面向实现的方式来完成了这一过程,并讨论了它的不足。随
后,我们先通过接口的使用对种族进行了抽象。接着,我们由将创建角色组成部分类的过程进行了封装,将这一过程委派给了工厂类。最后,我们又对工厂类进行了
抽象,最终实现了Abstract Factory工厂模式。
希望本文能给你带来帮助。
转载地址:http://www.tracefact.net/Design-Pattern/Abstract-Factory.aspx
分享到:
相关推荐
设计模式---抽象工厂模式(Abstract Factory)-UML图 (StarUML)
抽象工厂(Abstract Factory)设计模式是软件工程中一种重要的创建型设计模式,它提供了一种创建对象组的方式,这些对象属于同一族系并且彼此相关。这个模式的主要目标是定义一个接口,用于创建一族相关或相互依赖的...
1. 抽象工厂(Abstract Factory):这是模式的核心,定义了一组创建对象的接口,客户端通过这个接口请求创建所需的产品。这个接口不直接创建产品,而是将产品创建的职责委托给具体工厂。 2. 具体工厂(Concrete ...
Java设计模式是面向对象编程...在阅读《Chapter1___Java常用设计模式(SingleTon、FactoryMethod、AbstractFactory)》的相关资料时,你可以更深入地学习这些模式的细节,包括适用场景、优缺点以及如何在实际项目中实现。
1. 抽象工厂(Abstract Factory):这是模式的核心,它是一个接口或抽象类,定义了一系列创建对象的方法,但并不直接实例化具体的对象。这些方法用于创建一系列相关或相互依赖的对象。 2. 具体工厂(Concrete ...
1. **模式结构**:抽象工厂模式通常包括抽象工厂接口(AbstractFactory),具体工厂类(ConcreteFactory),抽象产品接口(Product)以及具体产品类(ConcreteProduct)。抽象工厂定义了创建产品的方法,而具体工厂...
* AbstractFactory:抽象工厂,定义了一个接口用于创建相关或依赖对象的家族。 * ConcreteFactory:具体工厂,继承AbstractFactory并实现了接口中的方法以创建具体的产品。 * AbstractProduct:抽象产品,定义了一个...
在这个例子中,`AbstractProductA`和`AbstractProductB`是抽象产品,`ConcreteProductA1/A2`和`ConcreteProductB1/B2`是具体产品,`AbstractFactory`是抽象工厂,`ConcreteFactory1/2`是具体工厂。客户端代码通过...
1. 抽象工厂(Abstract Factory):定义一个创建对象的接口,但不直接实现它,而是由子类来具体实现。这个接口通常包含了一系列创建产品对象的方法。 2. 具体工厂(Concrete Factory):实现抽象工厂接口,提供具体...
Abstract_Factory抽象工厂Abstract_Factory抽象工厂Abstract_Factory抽象工厂Abstract_Factory抽象工厂
Abstract Factory模式的核心在于抽象工厂(Abstract Factory)和具体工厂(Concrete Factory)。抽象工厂定义了一个用于创建一系列相关或相互依赖对象的接口,而具体工厂则实现了这些接口,负责生产实际的对象。这种...
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种创建对象集合的接口,而无需指定具体的产品类型。这种模式适用于当系统需要在不同平台或环境中创建一组相关或相互依赖的对象时,而这些...
抽象工厂(Abstract Factory)模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪一个类。这种模式是基于对象的抽象,而不是具体的类,因此,它允许创建一系列相关的对象,而无需指定...
1. **抽象工厂(Abstract Factory)**:这是核心接口,定义了创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。例如,一个`IWidgetFactory`可以创建各种不同类型的Widget对象。 2. **具体工厂...
1. **抽象工厂(Abstract Factory)**:这是模式的核心,它是一个接口或者抽象类,定义了创建一组相关或相互依赖对象的接口,而不必指定它们的具体类。在Java中,这个接口通常会包含多个方法,每个方法对应一种产品...
抽象工厂(Abstract Factory)模式是设计模式中的一种创建型模式,它提供了一种...在阅读提供的博客文章《AbstractFactory 抽象工厂》和研究压缩包中的相关文件时,你可以深入学习到更多关于这个模式的实践和应用场景。
1. 抽象工厂(Abstract Factory):定义一个创建对象的接口,使得子类决定实例化哪一个类。抽象工厂本身并不创建对象,而是返回一个实现了特定接口的对象引用。 2. 具体工厂(Concrete Factory):实现抽象工厂接口...
Abstract Factory模式 1 定义创建对象的接口,并封装对象的创建 2 将具体化类的工作延迟到了类中 3 创建创建一组相关对象或者说是一组相互依赖的对象 一般情况下,我们为了提高内聚和松耦合,经常会使用多态来...
抽象工厂模式是设计模式中的一种,属于创建型模式。它提供了一个创建对象族的接口,而无需指定其具体的类。这种模式的关键在于“家族”这个概念,即一系列相关的对象,它们可以相互协作以完成特定任务。在Java中,...
### 抽象工厂模式(Abstract Factory Pattern) #### 引入 在探讨抽象工厂模式之前,我们先回顾一下之前介绍过的简单工厂模式与工厂方法模式。这两种模式主要关注于解决对象创建过程中“new”操作的问题,使得创建...