为什么?
统一管理对象的创建过程式分为多种
工厂模式说起来很虚的感觉,如果构造函数很简单, 直接就可以new
出来。那还需要工厂模式做什么?
设计模式嘛,就是要将简单的东西标准化,用统一的模式或者方式去做某件事情,包括创建对象。更重要的是设计模式一直在强调解耦。怎么解耦?通常的方法就是中间加一层——抽象层,高层抽象,底层抽象都向这个中间层靠。
那换句话说,其实是在“封装”代码。将一些常用,会用到的代码进一步封装。
所以会看到,我就简单的new
一个对象怎么就要额外的添加那么多个类啊。
因为啊,以后底层的类可能要更改,底层类的构造函数可能要更改,如果使用了工厂模式,那么只需要改这一个抽象层就行了,不用在所有代码里挨个找。
简单工厂模式
这种模式不是标准的23中模式之一。因为它不符合开闭原则。当类新加子类的时候,需要修改代码。
简单工厂模式,统一的返回某个基类的子类实例。
UML
代码
//抽象层
class AbCar
{
public:
virtual void run()=0;
};
//各个子类
class BWM:public:AbCar
{
public:
virtual void run()
{
//dosomething
};
};
class QQ:public:AbCar
{
public:
virtual void run()
{
//dosomething
};
};
//创建工厂
class CarFactory
{
public:
AbCar create(string type)
{
if(type=="BMW")
{
return new BWM;
}elseif(type=="QQ")
{
return new QQ;
}
}else{
return nullptr;
}
}
如果有新加入的子类,那么就要修改CreateCar
,这不符合开闭原则。
但这是最近单的一类。用起来也很方便。
工厂模式
为了解决简单工厂模式不符合开闭原则的问题,出现了工厂模式。
工厂模式符合开闭原则。但是,引入了新的类,每一个实例类对应一个创建类。实例类共同继承一个抽象类,创建类共同继承另一个抽象类。两个抽象类之间有依赖关系。
使用时,要创建那个实例类,先创建对应的创建类。
UML
代码
//实例类的共同抽象类
class AbCar
{
public:
virtual void run()=0;
};
//具体的实例类
class BMW:public:AbCar
{
public:
virtual viod run()
{
}
private:
int engine;
};
//具体的实例类
class QQ:public:AbCar
{
public:
virtual viod run()
{
}
private:
int engine;
}
//创建类共同继承的虚类
class AbCarFactory
{
public:
virtual AbCar *create()=0
}
//具体的创建类
class BMWFactory:public AbCarFactory
{
public:
virtual AbCar *create()
{
return new BMW;
}
}
//具体的创建类
class QQFactory:public AbCarFactory
{
public:
virtual AbCar *create()
{
return new QQ;
}
}
//使用
int main()
{
AbCarFactory *factory=new QQFactory;
AbCar *qq=factory->create();
delete factory;
factory=nullptr;
//。。。
return 0;
}
在UML图的中间两层,可以无限的加新的类,新的类型的汽车。
可以看出来,其实更加复杂了有没有。但是如果以后car这个类的constructor
变化了,那么只需要修改对应的创建类即可。也就是又“封装了一层”。
抽象工厂模式
工厂模式有个缺点,就是一种创建类只能创建一种实例类的实例。
所以,抽象工厂组合了工厂模式和简单工厂模式。
也是因为这样,所以抽象工厂模式也是不符合开闭原则的。
将同一种类型的创建类合并,一个创建类中放多个createType()
函数,每一种type
对应返回一种实例类。
UML
代码
//实例类的共同抽象类
class AbCar
{
public:
virtual void run()=0;
};
//具体的实例类
class BMW01:public:AbCar
{
public:
virtual viod run()
{
}
private:
int engine;
};
//具体的实例类
class BMW01:public:AbCar
{
public:
virtual viod run()
{
}
private:
int engine;
}
//创建类共同继承的虚类
class AbCarFactory
{
public:
virtual AbCar *create()=0
}
//具体的创建类
class BMWFactory:public AbCarFactory
{
public:
virtual AbCar *createBMW01()
{
return new BMW01;
}
virtual AbCar *createBMW02()
{
return new BMW02;
}
}
//使用
int main()
{
AbCarFactory *factory=new BMWFactory;
AbCar *bmw=factory->createBMW01();
delete factory;
factory=nullptr;
//。。。
return 0;
}
创建类的抽象类的纯虚函数,在其子类中并没有什么作用,如果两个创建类中能创建的类型并没有共同的特点那?如果两个创建类能够创建的实例并不相同那?
那创建类的基类的纯虚函数,就是个摆设,或者是多余。并不符合借口隔离的原则。
所以我觉得这个抽象工厂模式的应用范围,真是窄。
总结
用的多的应该还是工厂模式。
简单工厂模式弊端大。需要按照参数类型进行创建。扩展不方便,
抽象工厂模式,对于一类产品的扩展和简单工厂模式一样,如果一个创建类要拓展一种创建类型,那么就要添加一个成员函数。如果使用基类继承过来的,那么基类也要加一个。而其他继承这个基类的子类,也新添加了一个类型吗?并不见得。
所以抽象工厂模式,应该应用在大型的,可能持久不变的项目中。
工厂模式更加接地气儿。