“设计模式”学习之一:工厂方法与抽象工厂
来源:互联网 发布:仿淘宝商城源码html 编辑:程序博客网 时间:2024/05/20 18:17
一、工厂方法(Factory method,别名“虚构造器” VitualConstructor)
1、引言
典型过程:试想当你手头拥有服装厂(抽象类A),要生产一种服装(抽象类B),而你现在还不确定先生产服装中的哪种(比如上衣类ConcreteB1、裤子类ConcreteB2)。此时,可以用工厂方法,依据股东们开会研究后的决定(相当于客户代码如main函数临时调用),使用不同的厂房进行具体服装的生产。作为股东,只需要在办公室拍板说:“上衣!”,那么服装厂就会启动上衣厂房开始生产。换句话说,股东不用与产房打交道,只需要让服装厂临时启动厂房。
2、一般思路
它是唯一一种用于类的创建型模式。由创建者Factory(抽象基类)提供创建接口,由其子类ConcreteFactory(具体创建类)决定实例化哪一个具体产品类ConcreteProduct。下图中引入内部成员变量Num,作为判定标准。
3、典型代码
(1)在上图 ConcreteFactory 类声明中:Product*CreateProduct();
(2)在CreateProduct(intNum)函数体中:if(Num == 1) return new ConcreteProduct1();
(3)客户调用代码main()中:
Factory* fac = new ConcreteFactory();
Product* p = fac->CreateProduct(1); // 1 or 2
可见:客户代码不再涉及与特定应用相关的类ConcreteProduct,只需调用接口。
4、应用提示
(1)一般而言,抽象基类Factory与Product存在一定的拥有关系(也就是书中提到的“聚合”)。例如,Application负责管理Document类。当然,也可连接两个平行的类层次,比如,图像类Figure和实现交互并保存所需操纵状态的类Manipulator;《Head first》中的Pizza和PizzaStore类。
(2)上图中的Factory基类也可以选择为具体类,这样为工厂方法(CreateProduct)提供一个缺省的实现,并且可以利用其子类改变父类创建的缺省ConcreteProduct类。
(3)为了使客户不用创建Factory的子类(即不用new ConcreteFactory()),可以使用模板,通过提供Factory的一个模板子类StandardCreator(以Product类作为模板参数)。这样客户只需要如下形式调用即可:StandardCreator<ConcreteProduct1> anyFactory;//不需要明确与ConcreteProduct1对应的**Factory子类名。
(4)一般称:Factory类提供了一个CreateProduct()工厂方法。而一般命名约定 用Class替代Product,如Class* DoMakeClass()。
(5)《Head first》引出了一个OO设计原则——“依赖倒置原则”:无论是高层组件还是低层,都要依赖抽象类,不要依赖具体类。PizzaStore和具体**Pizza都依赖于Pizza抽象类。引申过来,Factory类和ConcreteProduct1/2都依赖于Product类? 这个目前理解不透彻,还需要更进一步的体会。
(6)《Head first》提到的“简单工厂”没有完全符合“工厂方法”定义中的“定义一个接口”(即没有抽象层Factory,而是直接具体化)。故被称为一种编程习惯。
二、抽象工厂(Abstract Factory,别名“kit”)
1、引言
典型过程:在原服装厂的基础上,分立两个机构,分别负责童装和成人装的生产。同时在各个厂房分立两条工艺生产线。那么,股东同样只需要拍板说“产童装!”,不需要深入厂房,童装生产机构便会自动执行,生产出适合儿童的上衣和裤子。这就是典型的抽象工厂模式。
2、思路
下图中,提供了两个具体工厂,用于创建两个不同风格的产品系列1与2,各个产品系列当中都有A类和B类两种产品。当然,系列1中的A类产品有两种以上的选择,这是为了与上节中的工厂方法进行融合对比。作为客户,只需要与三个抽象接口打交道,不需要涉及产品的具体名称A1/2、B1/2。同时,这样可以保证同一个系列中产品风格的一致性和组件完整性。
3、典型代码
(1)在上图 ConcreteFactory1/2 类声明中:
AbstractProductA*CreateProductA(int Num);
AbstractProductB*CreateProductB();
(2)在ConcreteFactory1:: CreateProductB()函数体中:
return new ConcreteProductB1();
其它类似。
(3)客户调用代码main()中:
AbstractFactory*cf1 = new ConcreteFactory1();
cf1->CreateProductA(1);
cf1->CreateProductB();
AbstractFactory*cf2 = new ConcreteFactory2();
cf2->CreateProductA(1);
cf2->CreateProductB();
可见:客户代码不再涉及与特定应用相关的类ConcreteProductA2/B1/B2等。
4、应用提示
(1)如图所示,通常会为每个产品系列定义一个具体工厂方法(Factory Method模式的create**())。如果有多个可能的系列,具体工厂ConcreteFactory*可以考虑使用Prototype模式(待学),它可以使得不是每个新的产品系列都需要一个新的具体工厂类。
(2)对于Abstract Factory模式,如果需要增加新产品如类C,对于Abstract Factory接口及其所有子类,则需要增加CreateProductC(),如此扩展性很差。可以通过对CreateProduct()增加一个参数来实现。这样,AbstractFactory类只需要一个“Create”操作和一个指示要创建种类的参数。上图中,有借鉴这个思想,但是只是针对低层具体类,可以提升到高层来完全实现。
(3)通常,一个应用中每个产品系列只需一个具体工厂实例,故工厂最好用Singleton模式只生成一个。
三、两者关系
(1)分类的区别:Factory method模式是类模式,用于处理父类和子类的关系;Abstract Factory模式是对象模式,处理对象间的关系。
(2)功能区别:Abstract Factory是为创建一组(有多个类)相关的产品提供创建接口,而Factory method是为一类相似产品提供创建接口或延迟对象的创建到子类中实现。
(3)通常,Abstract Factory模式是使用Factory method模式实现的(ConcreteFactory1/2)。
- “设计模式”学习之一:工厂方法与抽象工厂
- 设计模式学习之简单工厂、工厂方法、抽象工厂
- 工厂设计模式之工厂方法与抽象工厂
- 设计模式-简单工厂、工厂方法与抽象工厂
- 设计模式之工厂方法模式与抽象工厂模式
- 设计模式之工厂方法模式与抽象工厂模式
- 设计模式:工厂方法与抽象工厂模式
- 设计模式-工厂模式(简单工厂,工厂方法,抽象工厂)
- 设计模式--工厂方法、抽象工厂模式
- 设计模式学习(二)之工厂模式(简单工厂+工厂方法+抽象工厂)
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 时间轴上 移出帧监听
- C语言的那些小秘密之指针(四)
- HTML DOM Button Object
- Vector使用
- C语言中可变形参简单实例和简单的printf功能的实例
- “设计模式”学习之一:工厂方法与抽象工厂
- 你的知识存储在大脑里还是存储在 Google 上?
- Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/s
- 玩转Android---组件篇---Service(服务)
- 程序开发基础学习二(C++ Google Style 命名规则)
- HTML Form Object
- apache portable runtime tutorial
- 解决Android requires compiler compliance level 5.0.错误
- 浅谈Android Service 组件