设计模式--创建型设计模式

创建型设计模式
创建型设计模式主要包含如下模式:
1、简单工厂模式
2、工厂方法(Factory Method)
3、抽象工厂模式(Abstract Method)
4、生成器(建造者)模式(Builder)
5、单例模式(Singleton)
1、工厂模式
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式作为一种创建模式,一般在创建复杂对象时,考虑使用;在创建简单对象时,建议直接new完成一个实例对象的创建。
1.1简单工厂方法
主要特点是需要在工厂类中做判断,从而创造相应的产品,当增加新产品时,需要修改工厂类。使用简单工厂模式,我们只需要知道具体的产品型号就可以创建一个产品。

缺点:工厂类(是一个非抽象类)集中了所有产品类的创建逻辑,如果产品量较大,会使得工厂类变的非常臃肿。

/*
关键代码:创建过程在工厂类中完成。
*/
#include <iostream>
using namespace std;
//定义产品类型信息
typedef enum
{
    Tank_Type_56,
    Tank_Type_96,
    Tank_Type_Num
}Tank_Type;

//抽象产品类
class Tank
{
public:
    virtual const string& type() = 0;
};

//具体的产品类
class Tank56 : public Tank
{
public:
    Tank56():Tank(),m_strType("Tank56")
    {
    }
    const string& type() override
    {
        cout << m_strType.data() << endl;
        return m_strType;
    }
private:
    string m_strType;
};
/*
关键代码:创建过程在工厂类中完成。
*/

#include <iostream>
using namespace std;
//定义产品类型信息
typedef enum
{
    Tank_Type_56,
    Tank_Type_96,
    Tank_Type_Num
}Tank_Type;
//抽象产品类
class Tank
{
public:
    virtual const string& type() = 0;
};

//具体的产品类
class Tank56 : public Tank
{
public:
    Tank56():Tank(),m_strType("Tank56")
    {
    }

    const string& type() override
    {
        cout << m_strType.data() << endl;
        return m_strType;
    }
private:
    string m_strType;
};

//具体的产品类
class Tank96 : public Tank
{
public:
    Tank96():Tank(),m_strType("Tank96")
    {
    }
    const string& type() override
    {
        cout << m_strType.data() << endl;
        return m_strType;
    }

private:
    string m_strType;
};

//工厂类
class TankFactory
{
public:
    //根据产品信息创建具体的产品类实例,返回一个抽象产品类
    Tank* createTank(Tank_Type type)
    {
        switch(type)
        {
        case Tank_Type_56:
            return new Tank56();
        case Tank_Type_96:
            return new Tank96();
        default:
            return nullptr;
        }
    }
};
int main()
{
    TankFactory* factory = new TankFactory();
    Tank* tank56 = factory->createTank(Tank_Type_56);
    tank56->type();
    Tank* tank96 = factory->createTank(Tank_Type_96);
    tank96->type();

    delete tank96;
    tank96 = nullptr;
    delete tank56;
    tank56 = nullptr;
    delete factory;
    factory = nullptr;
    return 0;
}

1.2 工厂方法(Factory Method)
别名虚构造器(virtual constructor),定义一个创建对象的接口,其子类去具体现实这个接口以完成具体的创建工作。如果需要增加新的产品类,只需要扩展一个相应的工厂类即可。

缺点:产品类数据较多时,需要实现大量的工厂类,这无疑增加了代码量。

/*
关键代码:创建过程在其子类执行。
*/
#include <iostream>
using namespace std;
//产品抽象类
class Tank
{
public:
    virtual const string& type() = 0;
};
//具体的产品类
class Tank56 : public Tank
{
public:
    Tank56():Tank(),m_strType("Tank56")
    {
    }
    const string& type() override
    {
        cout << m_strType.data() << endl;
        return m_strType;
    }
private:
    string m_strType;
};

//具体的产品类
class Tank96 : public Tank
{
public:
    Tank96():Tank(),m_strType("Tank96")
    {
    }
    const string& type() override
    {
        cout << m_strType.data() << endl;
        return m_strType;
    }
private:
    string m_strType;
};

//抽象工厂类,提供一个创建接口
class TankFactory
{
public:
    //提供创建产品实例的接口,返回抽象产品类
    virtual Tank* createTank() = 0;
};
//具体的创建工厂类,使用抽象工厂类提供的接口,去创建具体的产品实例
class Tank56Factory : public TankFactory
{
public:
    Tank* createTank() override
    {
        return new Tank56();
    }
};
//具体的创建工厂类,使用抽象工厂类提供的接口,去创建具体的产品实例
class Tank96Factory : public TankFactory
{
public:
    Tank* createTank() override
    {
        return new Tank96();
    }
};

int main()
{
    TankFactory* factory56 = new Tank56Factory();
    Tank* tank56 = factory56->createTank();
    tank56->type();

    TankFactory* factory96 = new Tank96Factory();
    Tank* tank96 = factory96->createTank();
    tank96->type();

    delete tank96;
    tank96 = nullptr;
    delete factory96;
    factory96 = nullptr;

    delete tank56;
    tank56 = nullptr;
    delete factory56;
    factory56 = nullptr;

    return 0;
}

1.3抽象工厂模式(Abstract Factory)
抽象工厂模式提供创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

当存在多个产品系列,而客户端只使用一个系列的产品时,可以考虑使用抽象工厂模式。

缺点:当增加一个新系列的产品时,不仅需要现实具体的产品类,还需要增加一个新的创建接口,扩展相对困难。
注意:抽象工厂模式与工厂模式最大的区别是:抽象工厂需要创建一系列产品,即一个抽象工厂方法需要创建多个产品,而一个工厂方法往往只需要创建一个产品

/*
* 关键代码:在一个工厂里聚合多个同类产品。
* 以下代码以白色衣服和黑色衣服为例,白色衣服为一个产品系列,黑色衣服为一个产品系列。白色上衣搭配白色裤子,   黑色上衣搭配黑色裤字。每个系列的衣服由一个对应的工厂创建,这样一个工厂创建的衣服能保证衣服为同一个系列。
*/

//抽象上衣类
class Coat
{
public:
    virtual const string& color() = 0;
};
//黑色上衣类
class BlackCoat : public Coat
{
public:
    BlackCoat():Coat(),m_strColor("Black Coat")
    {
    }

    const string& color() override
    {
        cout << m_strColor.data() << endl;
        return m_strColor;
    }
private:
    string m_strColor;
};

//白色上衣类
class WhiteCoat : public Coat
{
public:
    WhiteCoat():Coat(),m_strColor("White Coat")
    {
    }
    const string& color() override
    {
        cout << m_strColor.data() << endl;
        return m_strColor;
    }

private:
    string m_strColor;
};
?
//抽象裤子类
class Pants
{
public:
    virtual const string& color() = 0;
};

//黑色裤子类
class BlackPants : public Pants
{
public:
    BlackPants():Pants(),m_strColor("Black Pants")
    {
    }
    const string& color() override
    {
        cout << m_strColor.data() << endl;
        return m_strColor;
    }

private:
    string m_strColor;
};
?
//白色裤子类
class WhitePants : public Pants
{
public:
    WhitePants():Pants(),m_strColor("White Pants")
    {
    }
    const string& color() override
    {
        cout << m_strColor.data() << endl;
        return m_strColor;
    }

private:
    string m_strColor;
};

//抽象工厂类,提供衣服创建接口
class Factory
{
public:
    //上衣创建接口,返回抽象上衣类
    virtual Coat* createCoat() = 0;
    //裤子创建接口,返回抽象裤子类
    virtual Pants* createPants() = 0;
};

//创建白色衣服的工厂类,具体实现创建白色上衣和白色裤子的接口
class WhiteFactory : public Factory
{
public:
    Coat* createCoat() override
    {
        return new WhiteCoat();
    }

    Pants* createPants() override
    {
        return new WhitePants();
    }
};

//创建黑色衣服的工厂类,具体实现创建黑色上衣和白色裤子的接口
class BlackFactory : public Factory
{
    Coat* createCoat() override
    {
        return new BlackCoat();
    }
?
    Pants* createPants() override
    {
        return new BlackPants();
    }
};

2、生成器模式(Builder)
又称建造者模式:将复杂对象的构建和其表示分离,使得相同的构建过程可以产生不同的表示

以下情形可以考虑使用建造者模式:

对象的创建复杂,但是其各个部分的子对象创建算法一定。

需求变化大,构造复杂对象的子对象经常变化,但将其组合在一起的算法相对稳定。

建造者模式的优点:

将对象的创建和表示分离,客户端不需要了解具体的构建细节。

增加新的产品对象时,只需要增加其具体的建造类即可,不需要修改原来的代码,扩展方便。

产品之间差异性大,内部变化较大、较复杂时不建议使用建造者模式。

builder:先创建一个对象,里面包含一个对象不同部分的初始化方法。不同的产品对应不同的buider。
director: director中传入参数builder然后调用builder中不同部分的创建方法。

例如对于电脑而言,主要分为mac 和 windows等操作系统,除了操作系统之后,都包括主板、显示器等基本组成。

// 电脑基类
class Computer
{
	public:
	void setBoard(string board)
	{
		cout<<"set computer board"<<endl;
		mBoard = board;
	}
	void setDisplay(string display)
	{
		cout<<"set computer display\n";
		mDisplay = display;
	}
	virtual void setOS() = 0;
	private:
	string mBoard;
	string mDisplay;
	string mOS;
};
// 具体的电脑类
class MacComputer : public computer
{
	public:
	virtual void setOS()
	{
		cout<<"set MAC OS\n";
		mOS = "mac os";
	}
};
// 具体的电脑类
class WindowsComputer : public computer
{
	public:
	virtual void setOS()
	{
		cout<<"set Windows OS\n";
		OS = "Windows OS";
	}
};

// 抽象的builder,提供一个接口
class Builder
{
	public:
	// 接下来调用不同部分的建造函数,对产品进行初始化 接口
	virtual void buildBoard(string baord) = 0;
	virtual void buildDisplay(string display) = 0;
	virtual void buildOS() = 0;
	virtual computer * getComputer() = 0;
};

// 具体的builder
class MacBuilder : public Builder
{
	public:
	MacBuilder()
	{
		mcomputer = new MacComputer;
	}
	virtual void buildBoard(string board)
	{
		mcomputer->setBoard(board);
	}
	virtual void buildDisplay(string display)
	{
		mComputer->setDisplay(display);
	}
	virtual void setOS()
	{
		mComuter->setOs();
	}
	// 返回创建的产品
	virtual computer * getComputer()
	{
		return mComputer;
	}
	private:
	computer * mComputer;
};

// 可以类似创建windowsBuilder
class WindowsBuilder
{
};
// 下面是引导器director用来引导不同的创建过程

class Director
{
	private:
	builder * mbuilder; // 根据不同的builder来生成不同的产品
	public:
	Director(builder * builder)
	{
		mbuilder = builder;
	}
	// 引导产品的不同部分进行创建
	void construct(stirng board, string display)
	{
		mbuilder->buildBoard(board);
		mBuilder->buildDisplay(display);
		mBuilder->buildOs();
	}
};
	
		

/*
*关键代码:建造者类:创建和提供实例; Director类:管理建造出来的实例的依赖关系。
*/
#include <iostream>
#include <string>
using namespace std;
//具体的产品类
class Order
{
public:
    void setFood(const string& food)
    {
        m_strFood = food;
    }
    const string& food()
    {
        cout << m_strFood.data() << endl;
        return m_strFood;
    }

    void setDrink(const string& drink)
    {
        m_strDrink = drink;
    }
    const string& drink()
    {
        cout << m_strDrink << endl;
        return m_strDrink;
    }
?
private:
    string m_strFood;
    string m_strDrink;
};
//抽象建造类,提供建造接口。
class OrderBuilder
{
public:
    virtual ~OrderBuilder()
    {
        cout << "~OrderBuilder()" << endl;
    }
    virtual void setOrderFood() = 0;
    virtual void setOrderDrink() = 0;
    virtual Order* getOrder() = 0;
};
//具体的建造类
class VegetarianOrderBuilder : public OrderBuilder
{
public:
    VegetarianOrderBuilder()
    {
        m_pOrder = new Order;
    }
    ~VegetarianOrderBuilder()
    {
        cout << "~VegetarianOrderBuilder()" << endl;
        delete m_pOrder;
        m_pOrder = nullptr;
    }
    void setOrderFood() override
    {
        m_pOrder->setFood("vegetable salad");
    }
    void setOrderDrink() override
    {
        m_pOrder->setDrink("water");
    }
    Order* getOrder() override
    {
        return m_pOrder;
    }
?
private:
    Order* m_pOrder;
};
//具体的建造类
class MeatOrderBuilder : public OrderBuilder
{
public:
    MeatOrderBuilder()
    {
        m_pOrder = new Order;
    }
    ~MeatOrderBuilder()
    {
        cout << "~MeatOrderBuilder()" << endl;
        delete m_pOrder;
        m_pOrder = nullptr;
    }
    void setOrderFood() override
    {
        m_pOrder->setFood("beef");
    }
    void setOrderDrink() override
    {
        m_pOrder->setDrink("beer");
    }

    Order* getOrder() override
    {
        return m_pOrder;
    }

private:
    Order* m_pOrder;
};
//Director类,负责管理实例创建的依赖关系,指挥构建者类创建实例
class Director
{
public:
    Director(OrderBuilder* builder) : m_pOrderBuilder(builder)
    {
    }
    void construct()
    {
        m_pOrderBuilder->setOrderFood();
        m_pOrderBuilder->setOrderDrink();
    }
private:
    OrderBuilder* m_pOrderBuilder;
};
int main()
{
//  MeatOrderBuilder* mBuilder = new MeatOrderBuilder;
    OrderBuilder* mBuilder = new MeatOrderBuilder;  //注意抽象构建类必须有虚析构函数,解析时才会                                                      调用子类的析构函数
    Director* director = new Director(mBuilder);
    director->construct();
	Order* order = mBuilder->getOrder();
	order->food();
	order->drink();

	delete director;
	director = nullptr;
	delete mBuilder;
	mBuilder = nullptr;
	return 0;
}

3、原型模式(Protype)
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。通俗的讲就是当需要创建一个新的实例化对象时,我们刚好有一个实例化对象,但是已经存在的实例化对象又不能直接使用。这种情况下拷贝一个现有的实例化对象来用,可能会更方便。

以下情形可以考虑使用原型模式:

当new一个对象,非常繁琐复杂时,可以使用原型模式来进行复制一个对象。比如创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。

当需要new一个新的对象,这个对象和现有的对象区别不大,我们就可以直接复制一个已有的对象,然后稍加修改。

当需要一个对象副本时,比如需要提供对象的数据,同时又需要避免外部对数据对象进行修改,那就拷贝一个对象副本供外部使用。

/*
* 关键代码:拷贝,return new className(*this);
*/
#include <iostream>
using namespace std;
//提供一个抽象克隆基类。
class Clone
{
public:
    virtual Clone* clone() = 0;
    virtual void show() = 0;
};
//具体的实现类
class Sheep:public Clone
{
public:
    Sheep(int id, string name):Clone(),
                               m_id(id),m_name(name)
    {
        cout << "Sheep() id address:" << &m_id << endl;
        cout << "Sheep() name address:" << &m_name << endl;
    }
    ~Sheep()
    {
    }
    //关键代码拷贝构造函数
    Sheep(const Sheep& obj)
    {
        this->m_id = obj.m_id;
        this->m_name = obj.m_name;
        cout << "Sheep(const Sheep& obj) id address:" << &m_id << endl;
        cout << "Sheep(const Sheep& obj) name address:" << &m_name << endl;
    }
    //关键代码克隆函数,返回return new Sheep(*this)
    Clone* clone()
    {
        return new Sheep(*this);
    }
    void show()
    {
        cout << "id  :" << m_id << endl;
        cout << "name:" << m_name.data() << endl;
    }
private:
    int m_id;
    string m_name;
};
int main()
{
    Clone* s1 = new Sheep(1, "abs");
    s1->show();
    Clone* s2 = s1->clone();
    s2->show();

    delete s1;
    s1 = nullptr;
    delete s2;
    s2 = nullptr;
    return 0;
}

4、单例模式(Singleton)
单例模式顾名思义,保证一个类仅可以有一个实例化对象,并且提供一个可以访问它的全局接口。实现单例模式必须注意一下几点:

单例类只能由一个实例化对象。

单例类必须自己提供一个实例化对象。

单例类必须提供一个可以访问唯一实例化对象的接口。

单例模式分为懒汉和饿汉两种实现方式。
4.1懒汉单例模式
懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化一个对象。在访问量较小,甚至可能不会去访问的情况下,采用懒汉实现,这是以时间换空间。

/*
* 关键代码:构造函数是私有的,不能通过赋值运算,拷贝构造等方式实例化对象。
*/
//懒汉式一般实现:非线程安全,getInstance返回的实例指针需要delete
class Singleton
{
public:
    static Singleton* getInstance();
    ~Singleton(){}
?
private:
    Singleton(){}                                        //构造函数私有
    Singleton(const Singleton& obj) = delete;            //明确拒绝
    Singleton& operator=(const Singleton& obj) = delete; //明确拒绝

    static Singleton* m_pSingleton;
};
?
Singleton* Singleton::m_pSingleton = NULL;
?
Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        m_pSingleton = new Singleton;
    }
    return m_pSingleton;
}

线程安全懒汉单例模式
std::mutex mt;

class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝

    static Singleton* m_pSingleton;

};
Singleton* Singleton::m_pSingleton = NULL;

Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        mt.lock();
        if(m_pSingleton == NULL)
        {
            m_pSingleton = new Singleton();
        }
        mt.unlock();
    }
    return m_pSingleton;
}

4.2饿汉单例模式
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

//饿汉式:线程安全,注意一定要在合适的地方去delete它
class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝static Singleton* m_pSingleton;
};
​
Singleton* Singleton::m_pSingleton = new Singleton();
​
Singleton* Singleton::getInstance()
{
    return m_pSingleton;
}

参考文章
【1】https://www.cnblogs.com/chengjundu/p/8473564.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值