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

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

抽象工厂

我们使用一个汽车生产来做例子。抽象工厂模式如下:
有一个抽象工厂类名为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吧。

你可能感兴趣的:(cpp,设计模式)