工厂方法以及抽象工厂都是频率出现比较高的设计模式,他们属于创建型。
工厂方法
英文:Factory Method
使用频率:高
作用:
定义一个创建对象的接口,让子类决定创建什么样的实例对象。
说明:
工厂类有时候不仅仅表现为创建一个产品类并返回该产品类,他也可以表现为一种业务相关的类,并且自行维护这个创建的产品。
比如有时候单纯的为了创建对象,我们就将其当作工厂,只负责创建对象。
而比如文档编辑器,工厂就是编辑器,那么他除了负责创建文档对象,他还负责维护这些创建的对象,并且操作这些对象。
好处
比起用户直接创建具体的对象ConcreateProduct,我们可以解耦客户和具体的产品,并且复用基类的代码。如果需要添加类似的产品,那么添加对应的工厂和产品即可,方便扩展,遵守开放封闭原则。
对于下面的真是世界类图,也即是办公软件实现
可扩展:如果我需要增加ppt文件编辑器,那么直接复用IEditor和IDocument里面已经有的实现,基于这两个接口创建自己的子类。而在客户代码层面只需要创建PPTEditor就可以,创建对应的新的文档,以及操作该文档PPTDoc。
只需要将原来客户创建代码用新的PPTEditor代替TextEditor就可以了。其他的代码都不需要改动,便可以新建ppt文档,关闭ppt文档。(解耦带来的好处)
类图
结构化的类图
真实世界
假如我们需要实现办公软件,支持文本编辑器(比如word)/表单编辑器(excel),也就是图中的IEditor接口以及子类;而我们需要编辑文档,我们将文档抽象成IDocument。
比如编辑器支持创建文档/关闭文档等操作,他们直接与接口耦合,不耦合具体实现。
而新建文档NewDoc该新建文本文档还是表格文档呢,那就具体由子类决定,比如TextEditor就直接创建TextDoc,而SheetEditor创建SheetDoc。
这里面Editor相关类就是工厂,Document文档相关类就是产品对象,由Editor来创建。
代码
class AbstractProduct
{
public:
virtual void productMethod() = 0;
virtual ~AbstractProduct() {};
};
class ConcreteProductA : public AbstractProduct
{
virtual void productMethod()
{
cout << "ConcreteProductA" << endl;
}
};
class ConcreteProductB : public AbstractProduct
{
virtual void productMethod()
{
cout << "ConcreteProductB" << endl;
}
};
class AbstractFactory
{
public:
virtual AbstractProduct* factoryMethod() = 0;
virtual ~AbstractFactory() {};
};
class ConcreteFactoryA : public AbstractFactory
{
public:
virtual AbstractProduct* factoryMethod()
{
cout << "create concreteprodctA" << endl;
return new ConcreteProductA();
}
};
class ConcreteFactoryB : public AbstractFactory
{
public:
virtual AbstractProduct* factoryMethod()
{
cout << "create ConcreteProductB" << endl;
return new ConcreteProductB();
}
};
int main()
{
AbstractFactory* pFac = new ConcreteFactoryA;
AbstractProduct* pProduct = pFac->factoryMethod();
pProduct->productMethod();
return 0;
}
抽象工厂
英文:Abstract Factory
使用频率:高
作用:
提供一个接口用户创建一组关联或者依赖的对象,并且在接口不知道具体创建的类型。
说明:
其实和工厂方法比较像,但是他是创建了一组互相关联依赖的对象。注意不是简单的一个大工厂,创建一组无关的对象。如果无关,设计就有点不合理了。
类图:
比如形状工厂,用于创建线条/图形以及其他一些可扩展的形状;但是这个工厂具体要分文本文档和表格文档,他们创建的对象是不同的。文本文档中图形可以嵌入到文字里面,也可以相对位置摆放;但是表格是不必嵌入文字的。