设计模式之创造型模式

  • 单例模式

全局定义生成一个对象,声明周期跟整个程序一样

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
using namespace std;

class Singleton
{
public:

    static Singleton* getInstance()
    {
        return instance;
    }

private:
    //不让类的外部再创建实例
    Singleton() {

    }
    static Singleton* instance;//指向本类唯一实例的指针。
};

/*
饿汉式  - 在编译期间就已经确定这个唯一的实例了。
*/
Singleton*  Singleton::instance = new Singleton; //类的内部


class Singleton2
{
public:
    static Singleton2* getInstance()
    {
        //加锁
        if (instance == NULL) {
            instance = new Singleton2;
        }
        //关锁
        return instance;
    }

private:
    Singleton2() {

    }
    static Singleton2 * instance;
};


//懒汉式的初始化方式
Singleton2 *Singleton2::instance = NULL;


int main(void)
{
    Singleton * s1 = Singleton::getInstance();
    Singleton *s2 = Singleton::getInstance();

    if (s1 == s2) {
        cout << "s1 == s2" << endl;
    }
    else {
        cout << "s1 != s2 " << endl;
    }

    Singleton2 *s3 = Singleton2::getInstance();
    Singleton2 *s4 = Singleton2::getInstance();

    if (s3 == s4) {
        cout << "s3 == s4" << endl;

    }
    else {
        cout << "s3 != s4" << endl;
    }
    
    return 0;
}
  • 工厂方法模式

(指定的工厂生成指定的类)缺点就是需要生成多个工厂

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
using namespace std;

//抽象的水果类
class Fruit
{
public:
    virtual void getName() = 0;
};

class Apple :public Fruit {
public:
    virtual void getName() {
        cout << "我是苹果" << endl;
    }
};

class Banana :public Fruit {
public:
    virtual void getName() {
        cout << "我是香蕉 " << endl;
    }
};

//添加一个梨产品
class Pear : public Fruit
{
public:
    virtual void getName() {
        cout << "我是鸭梨 " << endl;
    }
};

//抽象的工厂类
class AbstractFactory
{
public:
    virtual Fruit * createFruit() = 0;//抽象的水果生产器
};

//苹果的工厂
class AppleFactory :public AbstractFactory
{
public:
    virtual Fruit * createFruit() {
        return new Apple;
    }
};

//香蕉工厂 
class BananaFactory : public AbstractFactory {
public:
    virtual Fruit *createFruit() {
        return new Banana;
    }
};

//添加梨的工厂
class PearFactory :public AbstractFactory
{
public:
    virtual Fruit *createFruit() {
        //....
        return  new Pear;
    }
};

int main(void)
{
    //1 给我来一个香蕉的工厂
    AbstractFactory * bananaFactory = new BananaFactory;
    //2 给我来一个水果
    Fruit * banana = bananaFactory->createFruit(); //只能够生成香蕉 //多态
    //Fruit *banana = new Banana;
    banana->getName(); //多态
    delete bananaFactory;
    delete banana;
    AbstractFactory *appleFactory = new AppleFactory;
    Fruit *apple = appleFactory->createFruit();
    apple->getName();
    AbstractFactory *pearFactory = new PearFactory;
    Fruit *pear = pearFactory->createFruit();
    //Fruit *pear = new Pear;
    pear->getName(); //多态
    
    return 0;
}
  • 抽象工厂模式(将产品归属一类,一个工厂生成一类产品,无需多个产品多个工厂)

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>

using namespace std;

// 0---------  抽象层 ------
class CPU
{
public:
    virtual void caculate() = 0; 
};

class Card
{
public:
    virtual void display() = 0;
};

class Memory
{
public:
    virtual void storage() = 0;
};

class AbstractFactory
{
public:
    virtual CPU* createCPU() = 0;
    virtual Card* createCard() = 0;
    virtual Memory * createMem() = 0;
};

//架构类
class Computer
{
public:
    Computer(CPU *cpu, Card *card, Memory *mem)
    {
        this->cpu = cpu;
        this->card = card;
        this->mem = mem;
    }

    void work() {
        this->cpu->caculate();
        this->card->display();
        this->mem->storage();
    }
private:
    CPU *cpu;
    Card*card;
    Memory *mem;
};

//抽象层结束------


// ----- 实现层-----
//intel厂商
class IntelCPU :public CPU
{
public:
    virtual void caculate() {
        cout << "Intel CPU 开始计算了..." << endl;
    }
};

class IntelCard :public Card
{
public:
    virtual void display() {
        cout << "Intel card 开始显示 了..." << endl;
    }
};

class IntelMem :public Memory
{
public:
    virtual void storage() {
        cout << "Intel mem 开始存储了..." << endl;
    }
};

class IntelFactory :public AbstractFactory
{
public:
    virtual CPU* createCPU()  {
        return new IntelCPU;
    }
    virtual Card* createCard() {
        return new IntelCard;
    }
    virtual Memory * createMem()  {
        return new IntelMem;
    }
};

 
// NVIDIA的厂商

class NvidiaCPU :public CPU
{
public:
    virtual void caculate() {
        cout << "Nvidia CPU 开始计算了..." << endl;
    }
};

class NvidiaCard :public Card
{
public:
    virtual void display() {
        cout << "Nvidia card 开始显示 了..." << endl;
    }
};

class NvidiaMem :public Memory
{
public:
    virtual void storage() {
        cout << "Nvidia mem 开始存储了..." << endl;
    }
};

class NvidiaFacory :public AbstractFactory
{
public:
    virtual CPU* createCPU()  {
        return new NvidiaCPU;
    }
    virtual Card* createCard() {
        return new NvidiaCard;
    }
    virtual Memory * createMem()  {
        return new NvidiaMem;
    }
};


// Kinston 厂商

class KinstonCPU :public CPU
{
public:
    virtual void caculate() {
        cout << "Kinston CPU 开始计算了..." << endl;
    }
};

class KinstonCard :public Card
{
public:
    virtual void display() {
        cout << "Kinston card 开始显示 了..." << endl;
    }
};

class KinstonMem :public Memory
{
public:
    virtual void storage() {
        cout << "Kinston mem 开始存储了..." << endl;
    }
};

class KinstonFacory :public AbstractFactory
{
public:
    virtual CPU* createCPU()  {
        return new KinstonCPU;
    }
    virtual Card* createCard() {
        return new KinstonCard;
    }
    virtual Memory * createMem()  {
        return new KinstonMem;
    }
};




int main(void)
{
    //1 组装一个intel系列的电脑 对intel公司的所有产品,执行一个单元测试。
    //创建一个intel的工厂
    AbstractFactory * intelFactory = new IntelFactory;
    CPU *intelCPU = intelFactory->createCPU();
    Card *intelCard = intelFactory->createCard();
    Memory *intelMem = intelFactory->createMem();

    Computer *com1 = new Computer(intelCPU, intelCard, intelMem);
    com1->work();


    cout << " -----  " << endl;

    //2 组装一个 intel的cpu  kinston card  NVIDIA的显卡的电脑
    AbstractFactory *kinstonFactory = new KinstonFacory;
    Memory *kingstonMem = kinstonFactory->createMem();
    AbstractFactory *nvidiaFactory = new NvidiaFacory;
    Card *nvidiaCard = nvidiaFactory->createCard();

    Computer *com2 = new Computer(intelCPU, nvidiaCard, kingstonMem);
    com2->work();
    return 0;
}
  • 简单工厂模式(一个工厂可以生成多个产品,每次新增产品都需要去修改工厂类,不符合软件设计规范)

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>

using namespace std;

class Fruit
{
public:
    Fruit(string kind)
    {
        this->kind = kind;
        if (kind == "apple") {
            //代表苹果
            //苹果的初始化方式
        }
        else if (kind == "banana") {
            //代表香蕉
            //香蕉的初始化方式
        }
    }

    void getName() {
        if (this->kind == "apple") {
            cout << "我是苹果" << endl;
        }
        else if (this->kind == "banana"){
            cout << "我是香蕉" << endl;
        }
    }
private:
    string kind;//代表水果的种类
};

int main(void)
{
    //创建一个苹果
    Fruit *apple = new Fruit("apple");
    apple->getName();
    delete apple;

    //main函数跟Fruit类的构造函数耦合度高, 随着水果种类的增加 构造函数越来越复杂
    
    return 0;
}
  • 建造者模式

1.0概念

(将一个复杂的对象的构造和表示分离使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象)

1.1作用:

指挥者(Director)直接和客户(Client)进行需求沟通;
沟通后指挥者将客户创建产品的需求划分为各个部件的建造请求(Builder);
将各个部件的建造请求委派到具体的建造者(ConcreteBuilder);
各个具体建造者负责进行产品部件的构建;
最终构建成具体产品(Product。

1.2主要作用:
  • 在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
  • 用户只需要给出指定复杂对象的类型和内容;
  • 建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)
1.3解决问题

方便用户创建复杂的对象(不需要知道实现过程)
代码复用性 & 封装性(将对象构建过程和细节进行封装 & 复用)

UML图
image.png
示例代码:

产品类


public class Bike { 

    private:
               IFrame frame; 
              ISeat seat; 
          ITire tire; 
    
    public :
    IFrame getFrame() { 
        return frame; 
    } 
    void setFrame(IFrame frame) { 
        this.frame = frame; 
    } 
    ISeat getSeat() { 
        return seat; 
    } 
    void setSeat(ISeat seat) { 
        this.seat = seat; 
    } 
    ITire getTire() { 
        return tire; 
    } 
    void setTire(ITire tire) { 
        this.tire = tire; 
    } 
} 

抽象Builder

public class Builder { 
    virtual void buildFrame(); 
    virtual void buildSeat(); 
    virtual void buildTire(); 
    virtual Bike createBike(); 
} 

具体Builder

// 具体 builder 类 
public class MobikeBuilder : public Builder{ 
    private Bike mBike = new Bike(); 
  public:   
 void buildFrame() { 
        mBike.setFrame(new AlloyFrame()); 
    } 
    void buildSeat() { 
        mBike.setSeat(new DermisSeat()); 
    } 
    void buildTire() { 
        mBike.setTire(new SolidTire()); 
    } 
    Bike createBike() { 
        return mBike; 
    } 
} 
指挥者
public class Director { 
    private:
     Builder mBuilder; 
    public:
     Director(Builder builder) { 
        mBuilder = builder; 
    } 
        Bike construct() { 
        mBuilder.buildFrame(); 
        mBuilder.buildSeat(); 
        mBuilder.buildTire(); 
        return mBuilder.createBike(); 
    } 
}
使用者
 private void showBike(Builder builder) {
        Director director = new Director(builder); 
        Bike bike = director.construct(); 
        bike.getFrame().frame(); 
        bike.getSeat().seat(); 
        bike.getTire().tire(); 
    } 
void mian(){
  showBike(new MobikeBuilder()); 
}

常规用发,使用者跟指挥者描述,指挥者调用具体的Builder,这样比在开发时候比较繁琐,一般没有指挥者,指挥者和Builder结合

项目中常用的方式
public class NewBuilder { 
    public:
    virtual void buildFrame(); 
    virtual  void buildSeat(); 
   virtual void buildTire(); 
    virtual Bike createBike(); 
    /** 
    * 把导演类中的construct()方法合并到抽象建造者类中 
    * @return 具体产品对象 
    */ 
    Bike construct() { 
        this.buildFrame(); 
        this.buildSeat(); 
        this.buildTire(); 
        return this.createBike(); 
    } 
} 

产品

// 省略 getter 和 setter 方法 
public class Computer { 
    private :
                String cpu; 
                String screen; 
               String memory; 
               String mainboard; 
    public :
      Computer(String cpu, String screen, String memory, String mainboard) { 
        this.cpu = cpu; 
        this.screen = screen; 
        this.memory = memory; 
        this.mainboard = mainboard; 
    } 
} 
public class NewComputer { 
    private:
               String cpu; 
                String screen; 
              String memory; 
              String mainboard; 
    public :
      NewComputer() { 
    } 
    private:
         NewComputer(Builder builder) { 
        cpu = builder.cpu; 
        screen = builder.screen; 
        memory = builder.memory; 
        mainboard = builder.mainboard; 
    } 
    public class Builder { 
        private:
                    String cpu; 
                    String screen; 
                    String memory; 
                    String mainboard; 
        
    public:
             Builder() {} 
             Builder cpu(String val) { 
          cpu = val; 
          return this; 
    } 
    Builder screen(String val) { 
        screen = val; 
        return this; 
    } 
      Builder memory(String val) { 
        memory = val; 
        return this; 
    } 
    Builder mainboard(String val) { 
        mainboard = val; 
        return this; 
    } 
    NewComputer build() {
        return new  NewComputer(this);} 
    } 
} 
使用
  void main() { 
        // 非 Builder 模式 
        Computer computer = new Computer(“cpu”, “screen”, “memory”, “mainboard”); 
        // Builder 模式 
        NewComputer newComputer = new NewComputer.Builder() 
        .cpu(“cpu”) 
        .screen(“screen”) 
        .memory(“memory”) 
        .mainboard(“mainboard”) 
        .build(); 
    } 

上面的示例代码只是传入四个参数,如果参数是十四个甚至更多,builder 模式的优势将会更加明显,传递参数更加灵活,代码具有更高的可读性.

优点

使用建造者模式可以使客户端不必知道产品内部组成的细节。
具体的建造者类之间是相互独立的,这有利于系统的扩展。
具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。

缺点

建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

  • 原型模式(用原型实例,创建对象的种类,并且通过拷贝这些原型创建新的对象)

UML 例图

image.png
例子代码
#include <iostream>
#include <string>
#include <list>
using namespace std;

//产品类
class Computer
{
public:
    void SetBrandName(string brandName)         //设置品牌
    {
        this->m_BrandName = brandName;
    }

    void SetCpu(string cpu)                     //设置CPU
    {
        this->m_Cpu = cpu;
    }

    void SetMemory(string memory)               //设置内存
    {
        this->m_Memory = memory;
    }

    void SetVideoCard(string videoCard)        //设置显卡
    {
        this->m_VideoCard=videoCard;
    }

    Computer Clone()                               //克隆函数
    {
        Computer ret;
        ret.SetBrandName(this->m_BrandName);
        ret.SetCpu(this->m_Cpu);
        ret.SetMemory(this->m_Memory);
        ret.SetVideoCard(this->m_VideoCard);
        return ret;
    }

    void ShowParams()                         //显示电脑相关信息
    {
        cout << "该款电脑相关参数如下:" << endl;
        cout << "品牌:" << this->m_BrandName << endl;
        cout << "CPU:" << this->m_Cpu << endl;
        cout << "内存:" << this->m_Memory << endl;
        cout << "显卡:" << this->m_VideoCard << endl;
    }

private:
    string m_BrandName;                         //品牌
    string m_Cpu;                               //CPU
    string m_Memory;                            //内存
    string m_VideoCard;                         //显卡
};

int main()
{
    //本例以电脑代工厂为例,分别生产同一配置,不同品牌的电脑

    //先生产华硕电脑
    Computer asusComputer;
    asusComputer.SetBrandName("华硕");
    asusComputer.SetCpu("I7 8700");
    asusComputer.SetMemory("16g");
    asusComputer.SetVideoCard("gtx 1080 ti");
    asusComputer.ShowParams();

    cout << endl;

    //再生产宏基电脑
    Computer acerComputer = asusComputer.Clone();
    acerComputer.SetBrandName("宏基");
    acerComputer.ShowParams();

    getchar();
    return 0;
}

对于相同类型的产品可以直接继承调用Clone,简约代码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容