设计模式之创建型模式

 创建型模式:创建对象的机制,从所需要实例化的对象中解耦。主要分成了五种设计模式,即工厂方法、抽象工厂、生成器、原型、单例。

工厂方法

 问题:一个物流公司最初只使用卡车运输,现需要增加轮船运输业务。目前的程序代码与卡车关联。
 解决方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
using namespace std;

//产品的接口
class Transport
{
public:
	virtual ~Transport() {};
	virtual void deliver() const = 0;
};

//产品A
class Truck :public Transport
{
public:
	void deliver() const override
	{
		std::cout << "卡车运输中ing\n";
	}
};

//产品B
class Ship :public Transport
{
public:
	void deliver() const override
	{
		std::cout << "轮船运输中ing\n";
	}
};

//创造者
class Logistics
{
public:
	virtual ~Logistics() {};
	virtual Transport* factoryMethod() const = 0;
	void doSomething()
	{
		Transport* transport = factoryMethod();
		transport->deliver();
		delete transport;
	}
};

//具体的创造者A
class TruckLogistis :public Logistics {
public:
	virtual ~TruckLogistis() {}
	virtual Transport* factoryMethod() const override {
		return new Truck();
	}
};
//具体的创造者B
class ShipLogistis :public Logistics {
public:
	virtual ~ShipLogistis() {}
	virtual Transport* factoryMethod() const override {
		return new Ship();
	}
};

int main()
{
	Logistics* truckLogistics = new TruckLogistis();
	Logistics* shipLogistics = new ShipLogistis();

	truckLogistics->doSomething();
	truckLogistics->doSomething();

	shipLogistics->doSomething();
	shipLogistics->doSomething();
	shipLogistics->doSomething();
	delete truckLogistics;
	delete shipLogistics;
	return 0;
}

在这里插入图片描述
缺点:应用工厂方法模式需要引入许多新的子类,代码可能会因此 变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

抽象工厂

 问题:家具店里有沙发、椅子、茶几等产品。产品有不同风格,如现代、北欧、工业。希望确保客户收到的产品风格统一,并可以方便的添加新产品和风格。
 解决方案:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
在这里插入图片描述
uml图
测试代码:

#include <iostream>
using namespace std;

class Chair
{
public:
	virtual~Chair() {};
	virtual void sitOn() const = 0;
};

class ModernChair :public Chair
{
public:
	virtual~ModernChair() {};
	void sitOn() const override
	{
		std::cout << "可以被坐下的ModernChair\n";
	}
};

class ChineseChair :public Chair
{
public:
	virtual~ChineseChair() {};
	void sitOn() const override
	{
		std::cout << "可以被坐下的ChineseChair\n";
	}
};

class Table
{
public:
	virtual~Table() {};
	virtual void putOn() const = 0;
};

class ModernTable :public Table
{
public:
	virtual~ModernTable() {};
	void putOn() const override
	{
		std::cout << "ModernTable可以放东西\n";
	}
};

class ChineseTable :public Table
{
public:
	virtual~ChineseTable() {};
	void putOn() const override
	{
		std::cout << "ChineseTable可以放东西\n";
	}
};

class FurnitureFacotry {//抽象工厂
public:
	virtual Chair* createChair() const = 0;
	virtual Table* createTable() const = 0;
};

class ModernStyleFactory :public FurnitureFacotry {
public:
	Chair* createChair() const override 
	{
		return new ModernChair();
	}

	Table* createTable() const override 
	{
		return new ModernTable();
	}
};

class ChineseStyleFactory :public FurnitureFacotry {
public:
	Chair* createChair() const override 
	{
		return new ChineseChair();
	}

	Table* createTable() const override 
	{
		return new ChineseTable();
	}
};

class Client
{
private:
	FurnitureFacotry* m_furniturefactory;
public:
	Client(FurnitureFacotry* furniturefactory)
	{
		setFactory(furniturefactory);
	}

	void buyFurniture()
	{
		Chair* chair = m_furniturefactory->createChair();
		Table* table = m_furniturefactory->createTable();
		chair->sitOn();
		table->putOn();
		delete chair;
		delete table;
	}

	void setFactory(FurnitureFacotry* furniturefactory)
	{
		m_furniturefactory = furniturefactory;
	}
};
int main()
{
	ModernStyleFactory modernFactory;
	Client client(&modernFactory);
	client.buyFurniture();

	ChineseStyleFactory chineseFactory;
	client.setFactory(&chineseFactory);
	client.buyFurniture();
	return 0;
}

在这里插入图片描述
缺点:在产品族中扩展新的产品需要修改抽象工厂的接口代码。

生成器

 问题:1、构造一个房屋,需要考虑是否有车库,游泳池,花园,雕塑等,需要对诸多成员变量进行初始化工作。都写在构造函数里?每种可能都创建一个新的类?2、相同的步骤需要能够产生不同的产品,例如使用木头和玻璃盖出来的是普通住房。用黄金和水晶建造出来的是宫殿。
 解决方案:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。即将对象构造代码从产品类中抽取出来,并将其放在一个名为Builder的独立对象中。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class SimpleHouse
{
public:
	std::vector<std::string> m_parts;
	void printParts() const
	{
		std::cout << "SimpleHouse 包括:\n";
		for (int i = 0; i < m_parts.size(); i++)
		{
			std::cout << m_parts[i] << std::endl;
		}
		std::cout << "-----------------------------------\n";
	}
};

class Builder
{
public:
	virtual ~Builder() {};
	virtual void reset() = 0;
	virtual void makeBaseHouse() = 0;
	virtual void makeGarage() = 0;
	virtual void makePool() = 0;
};

class SimpleHouseBuilder :public Builder
{
private:
	SimpleHouse* m_sh;
public:
	SimpleHouseBuilder()
	{
		reset();
	}

	~SimpleHouseBuilder()
	{
		if (m_sh)delete m_sh;
	}

	void reset() override
	{
		m_sh = new SimpleHouse;
	}

	void makeBaseHouse() override
	{
		m_sh->m_parts.push_back("BaseHouse");
	}

	void makeGarage() override
	{
		m_sh->m_parts.push_back("Garage");
	}

	void makePool() override
	{
		m_sh->m_parts.push_back("Pool");
	}

	SimpleHouse* getResult() 
	{
		SimpleHouse* result = m_sh;
		reset();
		return result;
	}
};
//主管:负责流程
class Director 
{
private:
	Builder* m_builder;
public:
	void setBuilder(Builder* builder)
	{
		m_builder = builder;
	}

	void makeSimpleHouse() 
	{
		m_builder->makeBaseHouse();
		m_builder->makeGarage();
	}

	void makeFullFuncHouse() 
	{
		m_builder->makeBaseHouse();
		m_builder->makeGarage();
		m_builder->makePool();
	}
};

void client(Director* director)
{
	std::cout << "客户自己设计流程.." << std::endl;
	SimpleHouseBuilder* shb = new SimpleHouseBuilder;
	shb->makeBaseHouse();
	shb->makeGarage();
	SimpleHouse* sh = shb->getResult();
	sh->printParts();
	delete sh;

	std::cout << "主管负责设计流程.." << std::endl;
	director->setBuilder(shb);
	director->makeFullFuncHouse();
	sh = shb->getResult();
	sh->printParts();

	delete sh;
	delete shb;
}

int main()
{
	Director dir;
	client(&dir);
	return 0;
}

在这里插入图片描述
 缺点:如果产品之间的差异性很大,则不适合使用建造者模式,使用范围受到一定的限制。

原型

 问题:希望复制一个状态完全相同的对象。首先,新建一个相同类的对象。 然后,复制所有成员变量。 但是,有时候不知道具体类型,而且成员变量可能是私有的。(从外部复制对象并非总是可行的)
 解决方案:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。即复制已有对象,而无需使代码依赖他们所属的类。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
#include <unordered_map>
using namespace std;

enum Type
{
	ROBOT_CAT = 0,
	ROBOT_DOG
};

class Robot
{
protected:
	std::string m_prototype_name = "";
	float m_stateOfCharge = 0;
public:
	virtual ~Robot() {};
	Robot(std::string prototype_name) :m_prototype_name(prototype_name) {}
	virtual Robot* clone()const = 0;
	virtual void setStateOfCharge(float) = 0;
};

class RobotCat :public Robot
{
private:
	float m_catValue;
public:
	RobotCat(std::string name,float value) :Robot(name), m_catValue(value) {}

	Robot* clone()const
	{
		return new RobotCat(*this);
	}

	void setStateOfCharge(float value)
	{
		m_stateOfCharge = value;
		std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge
			<< ",m_CatValue:" << m_catValue << std::endl;
	}
};

class RobotDog :public Robot
{
private:
	float m_dogValue;
public:
	RobotDog(std::string name,float value) :Robot(name), m_dogValue(value) {}

	Robot* clone()const
	{
		return new RobotDog(*this);
	}

	void setStateOfCharge(float value)
	{
		m_stateOfCharge = value;
		std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge
			<< ",m_dogValue:" << m_dogValue << std::endl;
	}
};

class cloneFactory
{
private:
	std::unordered_map<Type, Robot*> m_prototypes;
public:
	cloneFactory()
	{
		m_prototypes[ROBOT_CAT] = new RobotCat("机器猫", 5.0);
		m_prototypes[ROBOT_DOG] = new RobotCat("机器狗", 8.0);
	}
	~cloneFactory()
	{
		delete m_prototypes[ROBOT_CAT];
		delete m_prototypes[ROBOT_DOG];
	}
	Robot* createRobot(Type type) 
	{
		return m_prototypes[type]->clone();
	}
};

void client(cloneFactory&rf)
{
	std::cout << "克隆机器猫:\n";
	Robot* cloneRobot = rf.createRobot(ROBOT_CAT);
	cloneRobot->setStateOfCharge(90);
	delete cloneRobot;
	cloneRobot = rf.createRobot(ROBOT_CAT);
	cloneRobot->setStateOfCharge(80);
	delete cloneRobot;
	std::cout << "克隆机器狗:\n";
	cloneRobot = rf.createRobot(ROBOT_DOG);
	cloneRobot->setStateOfCharge(75);
	delete cloneRobot;
}

int main()
{
	cloneFactory rf;
	client(rf);
	return 0;
}

在这里插入图片描述
缺点:克隆包含循环引用的复杂对象可能会非常麻烦。

单例

 问题:对于一些类来说,只有一个实例是很重要的。例如数据库或其共享资源的访问权限。并且这个实例需要易于被访问。
 解决方案:保证一个类只有一个实例,并提供一个访问它的全局访问点。
在这里插入图片描述

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

class Singleton
{
private:
	Singleton(std::string value) :m_value(value) {};
	~Singleton() {};
	std::string m_value;
public:
	Singleton(Singleton& other) = delete;
	void operator=(const Singleton&) = delete;
	std::string value() const { return m_value; }
	static Singleton* getInstance(const std::string& value);
private:
	static Singleton* m_instance;
	static std::mutex m_mutex;
};

std::mutex Singleton::m_mutex;
Singleton* Singleton::m_instance = nullptr;

Singleton* Singleton::getInstance(const std::string& value)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	if (m_instance == nullptr) {
		m_instance = new Singleton(value);
	}
	return m_instance;
	//static Singleton* instance = new Singleton(value);
	//return instance;
}

void cat()
{
	Singleton* singleton = Singleton::getInstance("Cat");
	std::cout << singleton->value() << '\n';
}

void dog()
{
	Singleton* singleton = Singleton::getInstance("Dog");
	std::cout << singleton->value() << '\n';
}

int main()
{
	std::thread t1(cat);

	std::thread t2(dog);

	t1.join();
	t2.join();
	return 0;
}



在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值