设计模式(2)-抽象工厂模式(Abstract Factory)与生成器模式(Builder)模式

来源:互联网 发布:企业网络规划方案 编辑:程序博客网 时间:2024/05/18 01:06

抽象工厂和生成器模式常常被混淆,因为他们之间实在有很多的相似点,比如都是创建型模式,都隐藏产品具体细节,都向用户提供一个包含一系列接口的对象。
这个说法比较抽象。我们通过实现来看看为什么容易混淆。

抽象工厂

我们使用一个汽车生产来做例子。抽象工厂模式如下:
有一个抽象工厂类名为Factory,工厂的作用是生产车的不同部件。
有一个奔驰工厂BenzFactory继承了这个Factory,专门用来生产奔驰车的部件。
有一个奔驰工厂BMWFactory继承了这个Factory,专门用来生产宝马车的部件。
有一个消费者类Consumer,专门组装这些工厂生产的部件。

Class Factory{public:    virtua Car* createCar();//生产车    virtua Wheel* createWheel();//生产轮子    Shell* Wheel* createShell();//生产车壳    virtua Engine* createEngine();//生产引擎}Class BenzFactory:public Factory//奔驰工厂{    BenzCar* createCar();//生产奔驰车    Wheel* createWheel();//生产奔驰轮子    Shell* createShell();//生产奔驰车壳    Engine* createEngine();//生产奔驰引擎}Class BMWFactory:public Factory//宝马工厂{    BMWCar* createCar();//生产宝马车    Wheel* createWheel();//生产宝马轮子    Shell* createShell();//生产宝马车壳    Engine* createEngine();//生产宝马引擎}class Consumer{    Car* createCar(Factory * factory)    {        auto car= factory->createCar();        auto wheel= factory->createWheel();        auto shell= factory->createShell();        auto engine= factory->createEngine();        //一大堆组装过程,这里用户得自己处理        wheel->check();//轮胎检查        shell->check();//车壳检查        shell->setColor();//车壳上漆        engine->check();//引擎检查        car->add(wheel);        car->add(shell);        car->add(engine);        return car;    }}

Builder模式

Class Builder{public:    virtua Car* getCar();//最后Car组装完成后返回car    virtua Car* buildCar();//生成一个什么都没有的车    virtua Wheel* buildWheel();//生成轮子,并检查,组装    Shell* Wheel* buildShell();//生成车壳,并检查和喷漆,组装    virtua Engine* buildEngine();//生成引擎,并检查,组装protect:    Builder();}Class BenzBuilder:public Builder//奔驰工厂{public:    BenzCar* getCar(){return _current;};//得到组装后的奔驰车    virtua Car* buildCar(){_current=new BenzCar();};//生成一个什么都没有的奔驰车    Wheel* buildWheel();//生成奔驰轮子,并检查,组装    Shell* buildShell();//生成奔驰车壳,并检查和喷漆,组装    Engine* buildEngine();//生成奔驰引擎,并检查,组装private://注意与工厂模式的区别     BenzBuilder(){current=0};    BenzCar* _current;}Class BMWBuilder:public Builder//宝马工厂{public:    BMWCar* getCar(){return _current;};//得到组装完成的宝马车    virtua Car* buildCar(){_current=new BMWCar();};//生成一个什么都没有的宝马车    Wheel* buildWheel();//生成宝马轮子,并检查,组装    Shell* buildShell();//生成宝马车壳,并检查和喷漆,组装    Engine* buildEngine();//生成宝马引擎,并检查,组装private://注意与工厂模式的区别    BMWBuilder(){current=0};    BMWCar* _current;}class Consumer{    Car* getCar(Builder* builder)    {        builder->buildCar();        builder->buildWheel();        builder->buildShell();        builder-> buildEngine();        //对比工厂模式中的消费者,这里的消费者不需要自己去实现组装                  return builder->getCar();    }}

都有创建对象,都对用户提供一组接口,都有一个消费者,使用方式都是一样的。
需要注意的是上面的Consumer在抽象工厂模式被称为消费者,这个消费者把工厂生产的东西拿过来自己检查,自己喷漆,自己组装,是个DIY狂人。
但是Consumer在生成器模式中的定位更像是一个消费者,因为这个消费者不知道检查部件,不知道喷漆,不知道组装,但是他把任务交给了生成器类本身,自己只需要指明要用哪些东西罢了。

所以,他们之间的区别到底是什么呢?

  1. Builder类中的direction方法会替代Factory模式中消费者的部分工作,主要是隐藏了最终产品的实现细节,比如汽车的组装细节在Builder中被隐藏在Builder类内部,而Factory没有隐藏;

  2. Builder可以认为是将Factory再封装,所以,Builder没有Factory灵活,而Builder对于固定类型的对象创建更方便。消费者如果想要组装不同类型的东西,比如奔驰的引擎和宝马的外壳,那只能使用Factory模式。

使用Factory或Builder的好处

  1. 实现了消费者与产品类的解耦合,消费者只需要知道工厂类的生产对应产品的接口,无需知道具体有哪些产品实现类。
  2. 正因为解耦了高层调用类和低层实现类的关系,产品类具体如何变化,消费者是不关心的,修改只需要修改底层实现类,这为框架的扩展提供便利。

总结

工厂模式较Builder模式灵活,因为其支持一个零件一个零件的返回,用户可以自己选择零件拼装成一个对象。而Builder模式对创建复杂对象更方便,因为他将复杂对象的内部组装完全隐藏,用户不必劳神亲自每次都去自己创建一大队零件然后自己组装。
在设计的可扩展性和应用场景上,两个模式并没有太大的区别,他们都实现了用户和产品的解耦合,但是个人认为Builder模式实现的复杂性高一点。在使用上没有明显的区别的情况下,还是使用Factory吧。

阅读全文
0 0
原创粉丝点击