工厂方法与抽象工厂的区别
别名:虚构造器(Virtual Constructor)
意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
别名: 虚构造器,Virutal Constructor
动机:依然用一个实例来说明
Demo 考虑一个应用框架,它可以向用户显示多种文档。 两个抽象:Application(管理和创建Document),Document 例如绘图应用:DrawingApplication,DrawingDocument 特点:因为被实例化的特定Document子类是与特定应用相关的,所以Application类不可能预测到哪个Document子类将被实例化。 解决方案:封装哪一个Document子类将被创建的信息,并将这些信息从该框架中分离出来。 架构:
Application的子类重定义Application的抽象操作CreateDocument以返回适当的Document子类对象,一旦一个Application子类实例化以后,它就可以实例化与一个用相关的文档,而无需知道这些文档的类。
适用性 下列情况考虑使用FactZ http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcnkgTWV0aG9kxKPKvbWx0ru49sDgsrvWqrXAy/zL+bHY0Ou0tL2otcS21M/ztcTA4LXEyrG68rWx0ru49sDgz6PN+9PJy/y1xNfTwODAtNa4tqjL/Mv5tLS9qLXEttTP87XEyrG68rWxwOC0tL2ottTP87XE1rDU8M6vzdC4+LbguPaw79b619PA4LXExLPSu7j2o6yyosfSxOPPo837xMTSu7j2sO/W+tfTwODKx7T6wO3V39Xi0rvQxc+ivtayv7uvtcTKsbryCgq94bm5CjxpbWcgc3JjPQ=="https://www.cppentry.com/upload_files/article/76/1_twexh__.jpg" alt="\">
效果 不再将与特定应用相关的类绑定到你的代码中,代码仅处理Product接口 为子类提供挂钩:用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活 连接平行的类层次:工厂方法往往并不只是被Creator调用,客户可以找到一些有用的工厂方法。
解析: 平行类层次:当一个类将它的一些职责委托给一个独立的类时,就产生了平行类层次。
考虑一个例子 功能:对一个图形,用鼠标进行伸展、移动或者旋转 难点:需要存储和更新在给定时刻操作状态的信息;不同的图形有不同的行为 设计:Figure(图形类)、Manipulator(操作类,实现交互,保存操作相关状态)实现 1 当应用工厂方法模式时要考虑下面的问题:![]()
从Client的角度看,操作类层次和图形类层次是平行的。 Figure类提供一个CreateManipulator工厂方法,它使得客户可以创建一个与Figure相对应的Manipulator。
两种不同的情况
Creator类是一个抽象类,并且不提供它所声明的工厂方法(必须实例化子类才能使用) Creator类是一个具体类,而且为工厂方法提供一个缺省的实现()2 参数化工厂方法
工厂方法支持传递参数来创建多种产品 Demo 一个参数化的工厂方法具有如下的一般形式
class Creator {
public:
virtual Product* Creator(ProductId);
};
Product* Creator::Create (ProductId id) {
if (id == MINE) return new MyProduct;
if (id == YOURS) return new YourProduct;
return 0;
}
// 子类MyCreator继承Creator
product* MyCreator::Create (ProductId id)
{
if (id == YOURS) return new MyProduct;
if (id == MINE) return new YourProduct;
if (id == THEIRS) return new TheirProduct;
return Creator::Create(id); // 如果都不匹配,返回父类的Create
}
3 特定语言的变化和问题
在C++中记住一点,不要在Creator或者其子类的构造器中调用工厂方法。 访问者希望或得产品时,访问者首先检查一下该产品是否存在,如果产品不存在,访问者就创建它。这种技术称为lazy initialization。4 使用模板以避免创建子类
工厂方法的一个潜在问题就是,可能仅为了创建适当的Product对象而迫使你创建Creator子类。(当然,可以用参数化工厂方法来解决这个问题) 另一个解决办法:提供Creator一个模板子类,使用Product类作为模板参数。
class Creator {
public:
virtual Product* CreateProduct() = 0;
};
template
class StandardCreator: public Creator {
public:
virtual Product* CreateProduct() ;
}
template
Product* StandardCreator
::CreateProduct() { return new TheProduct; } // 使用这个模板 class MyProduct : public Product { public: MyProduct(); // ...... }; StandardCreator
myCreator;
5 命名约定
命名以清楚地说明你正在使用工厂方法
代码示例 使用工厂方法建造一个迷宫,使子类可以选择这些构件。每一个工厂方法返回一个给定类型的迷宫构件。
class MazeGame {
public:
Maze* CreateMaze();
virtual Maze* MakeMasze() const
{ return new Maze;}
virtual Room* MakeRoom(int n) const
{ return new Room(n) };
virtual Wall* MakeWall() const
从Client的角度看,操作类层次和图形类层次是平行的。 Figure类提供一个CreateManipulator工厂方法,它使得客户可以创建一个与Figure相对应的Manipulator。