【有毒的设计模式】建造者模式

版权声明:O.O 欢迎转载,如果我有能力写到原创文章的话~ https://blog.csdn.net/qq_16468937/article/details/51383115

//说些废话

已经有一个多月没写博客了,读书节买了一大堆书看,老“码”识途这本书好好玩,讲的好多机器语言啊汇编啊的知识,对理解框架有很好的作用,比较喜欢,还在钻研,本来想看完那一大堆书再写博客的,然后想了想,25本书,起码得一年才看得完,设计模式这么重要又不能一年后再写,不然都忘光了。然后翻了翻之前写的设计模式,果然自己写的博客才印象深刻,看一眼就记得自己用的什么例子和实现的要点在哪里,所以,还是坚持一下写博客吧。

话说,这个模式好烦,最起码四个类,然后其间的逻辑关系也是烦,理解后要用我觉得还是得慢慢想好类怎么构建的好,不然估计要写出一坨...


//部分资料来源

1.C++设计模式:http://www.jellythink.com/archives/98

2.程杰——大话设计模式


//正文



先来简单说说上面四个类各自的用途和各类之间的关系:

1.Man类:其实这个才是我们要用的那个东西,其他都是为了建造这个Man的。这个类就简单理解成我们最后要生成的产品。

2.Builder类:这个是个虚类,有什么用呢?就是用于对Man类进行一些更改操作的类的父类,提供了虚拟方法供重写。这个类内并不需要包含Man类成员。

3.FatManBuilder类、ThinManBuilder类:这个就是用于更改Man类操作的实用类,重写了Builder类提供的方法。这个类内需要包含要更改的Man类成员。

4.Director类:这个就是指挥类,用于指挥构建产品,其实就是指挥FatManBuilder / ThinManBuilder 的函数调用顺序。这个类内需要包含Builer类。


然后来看看我的代码:

#include <QCoreApplication>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Noodle
{
public:
    void Add(const string info)
    {
        NoodleVec.push_back(info);
    }

    void show()
    {
        for(vector<string>::iterator item = NoodleVec.begin();
            item != NoodleVec.end();item++)
        {
            cout<<*item<<" ";
        }
        cout<<"noodle";
    }

private:
    vector<string> NoodleVec;
};

class Chief
{
public:
    virtual void meat(){}
    virtual void noodle(){}
    virtual void egg(){}
    virtual void salt(){}
    virtual Noodle *getNoodle(){return nullptr;}
};

class AChief:public Chief
{
public:
    AChief(){MyNoodle = new Noodle();}
    void meat(){MyNoodle->Add("beef");}
    void noodle(){MyNoodle->Add("shrimp noodles");}
    void egg(){MyNoodle->Add("chicken egg");}
    void salt(){MyNoodle->Add("salt");}
    Noodle *getNoodle(){return MyNoodle;}

private:
    Noodle *MyNoodle;
};

class BChief:public Chief
{
public:
    BChief(){MyNoodle = new Noodle();}
    void meat(){MyNoodle->Add("pork");}
    void noodle(){MyNoodle->Add("bamboo noodles");}
    void egg(){MyNoodle->Add("duck egg");}
    void salt(){MyNoodle->Add("salt");}
    Noodle *getNoodle(){return MyNoodle;}

private:
    Noodle *MyNoodle;
};

class Director
{
public:
    Director(Chief *temp){TheChief = temp;}
    void CreateNoodle()
    {
        TheChief->meat();
        TheChief->noodle();
        TheChief->egg();
        TheChief->salt();
    }

private:
    Chief *TheChief;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Chief *chiefA = new AChief();
    Director *director = new Director(chiefA);
    director->CreateNoodle();
    Noodle *NoodleObj = chiefA->getNoodle();
    if(NoodleObj == nullptr)
        return 0;

    NoodleObj->show();

    return a.exec();
}


然后放个运行的截图吧:



那么解释一下:

1.Noodle类就是UML图中的Man类,是我们要做的面。

2.Chief类,就是Builder类,这提供了做面的抽象方法,加肉、加面、加蛋、加盐。

3.AChief类、BChief类,这个就是子类啦,这个提供了做面的具体方法,例如加什么肉?牛肉、猪肉?加什么面?虾子面、竹竿面?加什么蛋?鸡蛋、鸭蛋?

   就好像我的AChief类一样,是牛肉、虾子面、鸡蛋、盐。

   然而BChief类,是猪肉、竹竿面、鸭蛋、盐。(这个不知道能不能食)

   这样做就可以实现了需要建造的东西步骤一样,但具体的东西属性上有一点点差别。

4.Director类,上面那行说的建造的东西步骤一样,这里就是体现,这个类就是调用Chief类的方法的,想要什么顺序就什么顺序,你现在先加肉,再加面,再加蛋,再加盐。

   万一厨房来了个新主管,他说我做面要先放盐,再加面,再加蛋,再加肉。(这只是举例,现实中这样的面好可怕!)

   这样的话,我们只需要新建一个Director类,然后在实现中把Chief类中的方法调用顺序改改就行了。


这个就是建造者模式的好处

使得建造代码(Chief)与表示代码(Noodle)分离,由于建造者隐藏了该产品是如何组装(Director)的,所以若需要一个产品的内部表示,只需要再定义一个具体的建造者(AChief / BChief)就可以了


建造者模式:主要是用于创建一些复杂的对象(Noodle),这些对象内部构建间的建造顺序(Director)通常是稳定的,但对象内部的构建(AChief / BChief)通常面临复杂的变化。


那么说就说清楚了。


//问题

1.

Q:什么时候用建造者模式?

A: 当你要建造的东西内部(属性)建造顺序基本上是稳定的,然后具体建造的东西有区别。

       简单来说就是,你要按一个特定的流程去建造只有一点点不同的产品的时候就用。

       举例子来说就是,你麦当劳和肯德鸡,都是用一样的机器去做个汉堡,这个机器已经有了确立的顺序,先加菜、再加肉、再夹上面包。但是加原料有不同,例如你是加番茄酱还是芝士酱?生菜还是芽菜?


2.

Q:区分一下其他模式?

A:唔,这个虽然说得不知道准确不,不过按自己理解吧。

      简单工厂、工厂方法,这是为了隐藏类构造,不搭边。

      策略模式,这个我当时理解它就是多态,除了Context维护之外,其他就跟建造者模式Builder和其子类重写方法的作用一样了。

      SOLID原则,这个模式满足所有。

       装饰模式,这个不搭边吧。这个是为了扩展的。防止类爆炸。

       代理模式,就我举例那个牛油面包,没啥关系。

       原型模式,这个是那个为了克隆然后讨论了一大堆深浅拷贝的模式,没关系。

       模板方法模式,这个倒是有一点点关系,虽然模板方法模式是把逻辑骨架写在父类中,提供一些相应的抽象方法供子类重写,这个跟建造者有点像,因为建造者是把逻辑骨架放到director里面,然后builder提供虚方法给子类重写。那么我们不禁发问,为啥建造者模式要特别地把逻辑骨架放在一个独立的director类中呢?这是因为,建造者模式本来就是有保护表现的时候顺序会改变,就是说,你如果把逻辑骨架放到builder里面,那万一厨房真换了主管,先加盐的,那你就有改写builder类的逻辑骨架了,违反了开放-封闭原则对吧?除此之外,子类重写虚方法,实现部分属性不同这些都是一样的。还算相似吧。

        迪米特法则,这个是为了不要类暴露的,第三方调用,不搭边。

        外观模式,这个嘛,有一点点像吧,你可以理解成,director的方法就是一个facade,然后别人去调用这个facade就得到一个产品了,不过,外观模式压根就不改子系统的具体实现,所以,只能说一点带你关系,真的只有一点点。



猜你喜欢

转载自blog.csdn.net/qq_16468937/article/details/51383115
今日推荐