第26章 创建型模式大PK

26.1 工厂方法模式 VS 建造者模式

26.1.1 按工厂方法建造超人

(1)产品:两类超人,成年超人和未成年超人。

(2)工厂:这里选择简单工厂

【编程实验】工厂方法建造超人

//创建型模式大PK——工厂方法和建造者模式
//实例:利用简单工厂创建的超人
#include <iostream>
using namespace std;

//***************************抽象产品接口*********************
//超人接口
class ISuperMan
{
public:
    //每个超人都有特殊的技能
    virtual void specialTalent() = 0;

    virtual ~ISuperMan(){}
};

//*************************具体产品***********************
//成年超人
class AdultSuperMan : public ISuperMan
{
public:
    void specialTalent()
    {
        cout << "超人力大无穷" <<endl;
    }
};

//未成年人超人
class ChildSuperMan : public ISuperMan
{
public:
    void specialTalent()
    {
        cout << "小超人的能力是刀枪不入、快速移动" <<endl;
    }
};

//***********************简单工厂****************************
class SuperManFactory
{
public:
    static ISuperMan* createSuperMan(string type)
    {
        //根据输入参数产生不同的超人
        if(type == "adult")
        {
            return new AdultSuperMan();
        }
        else if (type == "child")
        {
            return new ChildSuperMan();
        }
        else
            return NULL;
    }
};

int main()
{
    //模拟生产超人(注意从生产工厂里出来的产品(如adult)都是一个模
    //样的,没有特殊的地方,这与后面的建造者模式有很大的不同)
    ISuperMan* sm = SuperManFactory::createSuperMan("child");
    //展示一下超人的技能
    sm->specialTalent();

    delete sm;

    return 0;
};

26.1.2 按建造者模式建造超人

(1)产品的三大组成部分:躯体、特殊技能、身份标记

(2)建造者:Builder。注意,与标准的建造者模式不同,这里的部件如何组装的过程由各个具体的建造者负责,而标准的作法是放到Director角色中去完成的。

//创建型模式大PK——工厂方法和建造者模式
//实例:利用建造者模式创建的超人
#include <iostream>
using namespace std;

//***************************辅助类*********************
//超人的身驱
class Body
{
    string body;
public:
    string& getBody(){return body;}
    void setBody(string value)
    {
        body = value;
    }
};

//特殊技能
class SpecialTalent
{
    string specialTalent;
public:
    string& getSpecialTalent(){return specialTalent;}
    void setSpecialTalent(string value)
    {
        specialTalent = value;
    }
};

//超人的标志
class SpecialSymbol
{
    string symbol;
public:
    string& getSymbol(){return symbol;}
    void setSymbol(string value)
    {
        symbol = value;
    }
};

//超人
class SuperMan
{
private:
    Body body;
    SpecialSymbol specialSymbol;
    SpecialTalent specialTalent;
public:
    string& getBody(){return body.getBody();}
    void setBody(string value)
    {
        body.setBody(value);
    }

    string& getSpecialTalent(){return specialTalent.getSpecialTalent();}
    void setSepcialTalent(string value)
    {
        specialTalent.setSpecialTalent(value);
    }

    string& getSpecialSymbol(){return specialSymbol.getSymbol();}
    void setSpecialSymbol(string value)
    {
        specialSymbol.setSymbol(value);
    }

    virtual ~SuperMan(){}
};

//*************************Builder角色***********************
//抽象建造者
class Builder
{
protected:
    SuperMan* superMan;
public:
    Builder()
    {
        superMan = new SuperMan();
    }

    //构建出超人的躯体
    void setBody(string value)
    {
        superMan->setBody(value);
    }

    //构建出超人的特殊技能
    void setSpecialTalent(string value)
    {
        superMan->setSepcialTalent(value);
    }

    //构建出超人的特殊标记
    void setSpecialSymbol(string value)
    {
        superMan->setSpecialSymbol(value);
    }

    //构建出一个完整的超人
    //超人的各个部件都准备好了,具体怎么组装由实现类来决定,
    //体现建造者模式将复杂对象的构建和表示分离的意图
    virtual SuperMan* getSuperMan() = 0;

    virtual ~Builder()
    {
        delete superMan;
    }
};

//成年超人建造者
class AdultSuperManBuilder :public Builder
{
public:
    SuperMan* getSuperMan()
    {
        //1.标准的建造者模式,建造过程是放在Director中进行装配的。
        //2.建造者模式关注产品的各个部分,甚至构建顺序,
        //  即相同的部件,装配顺序不同,产生的结果也可能不同,
        //  这正是建造者模式的意图)
        superMan->setBody("强壮的躯体");
        superMan->setSepcialTalent("会飞行");
        superMan->setSpecialSymbol("胸前带S标记");

        return superMan;
    }
};

//未成年超人建造者
class ChildSuperManBuilder :public Builder
{
public:
    SuperMan* getSuperMan()
    {
        //建造过程
        superMan->setBody("强壮的躯体");
        superMan->setSepcialTalent("刀枪不入");
        superMan->setSpecialSymbol("胸前带小S标记");

        return superMan;
    }
};

//导演类
class Director
{
private:
    static Builder* adultBuilder;
    static Builder* childBuilder;
public:
    //本例中,以下函数只是一个空壳,而标准的建造者模式
    //其部件的组装过程是在以下两部函数中完成的!

    //建造一个成人超人
    static SuperMan* getAdultSuperMan()
    {

        return adultBuilder->getSuperMan();
    }

    //建造一个未成年人超人
    static SuperMan* getChildSuperMan()
    {
        return childBuilder->getSuperMan();
    }
};
Builder* Director::adultBuilder = new AdultSuperManBuilder();
Builder* Director::childBuilder = new ChildSuperManBuilder();

int main()
{
    //建造一个超人
    SuperMan* sm = Director::getAdultSuperMan();
    //SuperMan* sm = Director::getChildSuperMan();

    //展示一个超人的能力
    cout << "超人的身体:" << sm->getBody() << endl;
    cout << "超人的特殊能力:" << sm->getSpecialTalent() << endl;
    cout << "超人带的标志:" << sm->getSpecialSymbol() << endl;

    return 0;
};
/*输出结果
超人的身体:强壮的躯体
超人的特殊能力:会飞行
超人带的标志:胸前带S标记
*/

26.1.3 最佳实践

(1)意图不同

  ①工厂方法模式,关注的是一个产品整体无须关心产品各部分是如何创建出来的。

  ②建造者模式,一个具体产品的产生是依赖各个部件的产生以及装配顺序,它关注的是由零件一步一步地组装出产品对象

  ③简单理解,工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线程勾勒出一个复杂对象,关注的是产品组成部分的创建过程。

(2)产品的复杂度不同

  ①工厂方法模式创建的产品一般都是单一性质产品,都是一个模样

  ②建造者模式创建的则是一个复合产品,它则各个部件复合而成,部件不同,产品对象当然不同。

  ③一般来说工厂方法模式创建的产品的粒度比较粗,而建造者模式的产品对象粒度比较细。

(3)方法的选择:如果关注一个产品部件的生产、安装步骤,则选择建造者否则选择工厂方法模式

26.2 抽象工厂模式 VS 建造者模式

26.2.1 抽象工厂模式

(1)产品等级:宝马(BWM)、奔驰(Benz)

(2)产品族:即车型(如商务车型Van、运动型SUV),即每个工厂要生产两种车型

【编程实验】按抽象工厂模式生产车辆

 

//创建型模式大PK——抽象工厂方法和建造者模式
//实例:利用抽象工厂方法生产汽车
#include <iostream>
using namespace std;

//抽象产品
class  ICar
{
public:
    //获取汽车生产商,即品牌
    virtual string getBand() = 0;
    //获取汽车的型号
    virtual string getModel() = 0;
};

//抽象宝马车
class AbsBMW : public ICar
{
   string BMW_BNAD;
public:
    AbsBMW()
    {
        BMW_BNAD = "宝马汽车";
    }

    string getBand()
    {
        return BMW_BNAD;
    }
};

//宝马商务车
class BMWVan :public AbsBMW
{
    string SEVENT_SEARIES;
public:
    BMWVan():AbsBMW()
    {
        SEVENT_SEARIES = "7系列商务车";
    }
    string getModel()
    {
        return SEVENT_SEARIES;
    }
};

//宝马Suv
class BMWSuv :public AbsBMW
{
    string X_SEARIES;
public:
    BMWSuv():AbsBMW()
    {
        X_SEARIES = "x系列Suv";
    }
    string getModel()
    {
        return X_SEARIES;
    }
};

//抽象奔驰车
class AbsBenz : public ICar
{
   string BENZ_BNAD;
public:
    AbsBenz()
    {
        BENZ_BNAD = "奔驰汽车";
    }

    string getBand()
    {
        return BENZ_BNAD;
    }
};

//奔驰商务车
class BenzVan :public AbsBenz
{
    string R_SEARIES;
public:
    BenzVan():AbsBenz()
    {
        R_SEARIES = "R系列商务车";
    }
    string getModel()
    {
        return R_SEARIES;
    }
};

//奔驰Suv
class BenzSuv :public AbsBenz
{
    string G_SEARIES;
public:
    BenzSuv():AbsBenz()
    {
        G_SEARIES = "G系列Suv";
    }
    string getModel()
    {
        return G_SEARIES;
    }
};

//抽象工厂
class CarFactory
{
public:
    //生产SUV型
    virtual ICar* createSuv() = 0;
    //生产商务车型
    virtual ICar* createVan() = 0;
};

//宝马车工厂
class BMWFactory : public CarFactory
{
public:
    ICar* createSuv()
    {
        return new BMWSuv();
    }

    ICar* createVan()
    {
        return new BMWVan();
    }
};

//奔驰车工厂
class BenzFactory : public CarFactory
{
public:
    ICar* createSuv()
    {
        return new BenzSuv;
    }

    ICar* createVan()
    {
        return new BenzVan();
    }
};

int main()
{
    //要求生产一辆奔驰车
    cout <<"===要求生产一辆奔驰车SUV===" << endl;
    //首先找奔驰车的工厂
    CarFactory* carFactory = new BenzFactory();
    //开始生产
    ICar* car = carFactory->createSuv();
    //生产完毕,展示一下车辆信息
    cout << "===车辆生产完毕,详细信息如下===" << endl;
    cout << "汽车品牌:" << car->getBand() <<endl;
    cout << "汽车型号:" << car->getModel() <<endl;

    return 0;
};
/*输出结果
 ===要求生产一辆奔驰车SUV===
===车辆生产完毕,详细信息如下===
汽车品牌:奔驰汽车
汽车型号:G系列Suv
*/

26.2.2 建造者模式

(1)整体:汽车。部分:引擎和车轮

(2)Builder:BenzBuilder和BMWBuilder

【编程实验】按建造者模式生产车辆

 

//创建型模式大PK——抽象工厂方法和建造者模式
//实例:利用建造者模式生产汽车
#include <iostream>
using namespace std;

//**********************辅助类*******************************
//生产蓝图(这个蓝图会交给Director,让他这个要求去生产汽车)
class Blueprint
{
private:
    string wheel;   //车轮的要求
    string engine;  //引擎的要求
public:
    string getWheel(){return wheel;}
    void setWheel(string value)
    {
        wheel = value;
    }

    string getEngine(){return engine;}
    void setEngine(string value)
    {
        engine = value;
    }
};

//车辆产品
class ICar
{
public:
    //汽车车轮
   virtual string getWheel() = 0;
   //汽车引擎
   virtual string getEngine() = 0;
   //显示信号
   virtual string toString() = 0;
   virtual ~ICar (){}
};

//具体车辆
class Car : public ICar
{
private:
    string engine;  //引擎
    string wheel;   //车轮
public:
    Car(string engine, string wheel)
    {
        this->engine = engine;
        this->wheel = wheel;
    }

    string getEngine()
    {
        return engine;
    }
    string getWheel()
    {
        return wheel;
    }

    //演示车辆信息
    string toString()
    {
        return "车的轮子是:" + wheel + "
车的引擎是:" + engine;
    }
};

//抽象建造者
class CarBuilder
{
private:
    //ICar* car; //等建造的汽车
    Blueprint* bp; //设计蓝图
protected:
    //只有具体的建造者才可以查看蓝图
    Blueprint* getBlueprint(){return bp;}
public:
    //接收一份设计蓝图
    void setBlueprint(Blueprint* value)
    {
        bp = value;
    }

    //部件的构建
    virtual string buildWheel() = 0;
    virtual string buildEngine() = 0;

    //按照顺序生产一辆车
    Car* buildCar()
    {
        return  new Car(buildEngine(),buildWheel());
    }
    virtual ~CarBuilder(){}
};

//宝马车建造车间
class BMWBuilder : public CarBuilder
{
public:
    string buildEngine()
    {
        //按车间主任(Director)手里的蓝图进行设计
        return getBlueprint()->getEngine();
    }

    string buildWheel()
    {
        //按车间主任(Director)手里的蓝图进行设计
        return getBlueprint()->getWheel();
    }
};

//奔驰车建造车间
class BenzBuilder : public CarBuilder
{
public:
    string buildEngine()
    {
        //按车间主任(Director)手里的蓝图进行设计
        return getBlueprint()->getEngine();
    }

    string buildWheel()
    {
        //按车间主任(Director)手里的蓝图进行设计
        return getBlueprint()->getWheel();
    }
};

//导演类:Director
class Director
{
private:
    //持有建造者的引用
    CarBuilder* bmwBuilder;
    CarBuilder* benzBuilder;
public:
    Director()
    {
        bmwBuilder = new BMWBuilder();
        benzBuilder = new BMWBuilder();
    }
    //生产车辆
    ICar* createCar(CarBuilder* carBuilder, string engine, string wheel)
    {
        //导演手中的蓝图
        Blueprint bp;
        bp.setEngine(engine);
        bp.setWheel(wheel);
        carBuilder->setBlueprint(&bp);
        return carBuilder->buildCar();
    }
    //生产奔驰SUV
    ICar* createBenzSuv()
    {
        return createCar(benzBuilder, "benz的引擎","benz的轮胎");
    }

    //生产宝马商务
    ICar* createBMWVan()
    {
        return createCar(bmwBuilder, "BMW的引擎","BMW的轮胎");
    }

    //生产混合车型
     ICar* createComplexCar()
    {
        return createCar(bmwBuilder, "BMW的引擎","benz的轮胎");
    }

    ~Director()
    {
        delete benzBuilder;
        delete bmwBuilder;
    }
};

int main()
{
    //定义一个导演类
    Director director;
    //生成一辆奔驰车SUV
    cout <<"===制造一辆奔驰SUV===" << endl;
    ICar* benzSuv = director.createBenzSuv();
    cout << benzSuv->toString() << endl;

    cout <<"===制造一辆宝马商务车===" << endl;
    ICar* bmwVan = director.createBMWVan();
    cout << bmwVan->toString() << endl;

    cout <<"===制造一辆混合车===" << endl;
    ICar* complexCar = director.createComplexCar();
    cout << complexCar->toString() << endl;

    delete benzSuv;
    delete bmwVan;
    delete complexCar;

    return 0;
};
/*输出结果
===制造一辆奔驰SUV===
车的轮子是:benz的轮胎
车的引擎是:benz的引擎
===制造一辆宝马商务车===
车的轮子是:BMW的轮胎
车的引擎是:BMW的引擎
===制造一辆混合车===
车的轮子是:benz的轮胎
车的引擎是:BMW的引擎
*/

26.2.3 最佳实践

(1)抽象工厂模式只关心一个工厂到底生产了哪些产品,不关心具体怎么生产的。

(2)建造者模式要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新的产品

(3)抽象工厂使用“工厂”来描述产品的构建,它是一种更高层次看对象的构建,而建造者使用“车间”来描述,不同的车间完成不同的创建和装配任务,一个完整的汽车生产过程需要引擎制造车间、引擎装配车间的配合才能完成,它们配合的基础是设计蓝图,而这个蓝图掌握在车间主任(Director)手中,它给建造者车间什么蓝图就能生产什么产品,它更关心建造过程。

(4)相对来说,抽象工厂模式比建造者模式的尺度更大,它关注产品整体,而建造者模式关注的是构建过程

(5)如果希望屏蔽对象的创建过程,只提供一个良好的封装,可以选择抽象工厂模式。如果在构件时通过不同的装配产生出新的对象,可以使用建造者模式。

原文地址:https://www.cnblogs.com/5iedu/p/5655196.html