一、定义
工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
二、结构图
工厂方法模式不同于简单工厂模式的地方在于工厂方法模式把对象的创建过程放到里子类里。这样工厂父对象和产品父对象一样,可以是抽象类或者接口,只定义相应的规范或操作,不涉及具体的创建或实现细节。
三、例子
(1)产品基类
class IProduct
{
IProduct();
virtual ~IProduct();
};
(2)产品A子类
class ProductA : public IProduct
{
ProductA();
~ProductA();
};
(3)产品B子类
class ProductB : public IProduct
{
ProductB();
~ProductB();
};
(4)工厂基类
class IFactory
{
public:
IFactory();
virtual ~IFactory();
virtual IProduct* getProduct();
};
(5)产品A工厂类
class ProductAFactory : public IFactory
{
public:
ProductAFactory();
~ProductAFactory();
virtual IProduct* getProduct()
{
return new ProductA();
}
};
(6)产品B工厂类
class ProductBFactory : public IFactory
{
public:
ProductBFactory();
~ProductBFactory();
virtual IProduct* getProduct()
{
return new ProductB();
}
};
(7)客户端调用
int main()
{
IFactory *factory = new ProductAFactory();
IProduct *product = factory->getProduct();
factory = new ProductBFactory();
product = factory->getProduct();
return 0;
}
四、适用性
(1) .net里面的数据库连接对象就是产生数据命令对象的工厂。每种数据库的connection对象里(继承自IDbConnection)都有对自己createCommand(定义在IDbCommand里)的实现。
(2) .net里面的迭代器,IEnumerable定义了迭代器的接口,即工厂方法,每一个继承自IEnumerable的类都要实现GetEnumerator。可以参看ArrayList,String的GetEnumerator方法。他们都继承自IEnumerable。
五、优点
(1) 核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
(2) 从类关系上来说,它可以让客户端与具体的工厂与产品解耦,从业务角度来说,它让客户端与具体的产品解耦。
六、缺点
增加了几个具体工厂类,使得类结构变得更复杂。
七、对比
(1) 简单工厂:工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖,但违背了开放-封闭原则。
(2) 工厂方法:客户端需要实例化哪一个工厂来实现,在添加功能上,本来是改工厂类,但现在是修改客户端。
参考资料:
1.《大话设计模式》程杰著