设计模式

参考:
《大话设计模式》
爱编程的大丙

设计原则

  1. 单一职责原则:每个类应仅仅负责一种功能逻辑
  2. 开放封闭原则:对原有的代码封闭,不能修改。对新的功能开放,可以扩展。在设计时,尽量抽象出以后不会改变的类,之后有新的改动可以通过增加新代码,而不改变原有类的方法实现。比如在客户端类中实现四则运算,每增加一种运算就要修改类,可以将运算中不变的抽象出来,之后每增加新的运算,在此基础上扩展就好。
  3. 依赖倒转原则:抽象不依赖细节,细节依赖抽象。高层模块与底层模块不应该相互依赖,应该都依赖与一个接口(c++就是抽象类),实现各模块的主要目标是实现这个接口。
  4. 迪米特(最少知识)原则:每个类应尽量减少自己成员和方法的访问权限。两个类如果不直接通信就不应直接相互作用,如果需要调用另一个类的方法,应该通过第三方调用
  5. 合成聚合原则:优先使用合成聚合,尽量不要使用类继承
  6. 里氏代换原则:子类型必须能替换父类型

创建型模式

简单工厂模式

当实例化不同对象,且经常变化时,考虑使用。但是不满足开放封闭原则。
一个抽象运算类,加减乘除四个运算类继承这个抽象类,运算工厂类依赖于抽象运算类,负责根据输入的符号构造具体的四个运算类
img

#include<iostream>
class Operator
{
public:
	virtual int GetResult() { return 0; }
	int a=0;
	int b=0;
};
class AddOperator :public Operator
{
	int GetResult() override
	{
		return a + b;
	}
};
class SubOperator :public Operator
{
	int GetResult() override
	{
		return a - b;
	}
};
class MulOperator :public Operator
{
	int GetResult() override
	{
		return a * b;
	}
};
class DivideOperator :public Operator
{
	int GetResult() override
	{
		if (b != 0)
		{
			return a / b;
		}
		else
		{
			throw "除数不能为零";
		}
	}
};
class OperatorFactory
{
public:
	static Operator* Createoperator(char sign)
	{
		Operator *oper=nullptr;
		switch (sign)
		{
		case '+':
			oper = new AddOperator();
			break;
		case '-':
			oper = new SubOperator();
			break;
		case '*':
			oper = new MulOperator();
			break;
		case '/':
			oper = new DivideOperator();
			break;
		}
		return oper;
	}
};
int main()
{
	Operator *oper = OperatorFactory::Createoperator('/');
	oper->a = 6;
	oper->b = 3;
	int r = oper->GetResult();
	std::cout << r;
}

工厂模式

简单工厂模式需要修改工厂类,违反开放封闭原则。工厂模式为工厂类抽象一个接口,其子类来分别实现接口,这样运算类与工厂类就互不依赖
img

#include<iostream>
class Operator
{
public:
	virtual int GetResult() { return 0; }
	int a = 0;
	int b = 0;
};
class AddOperator :public Operator
{
	int GetResult() override
	{
		return a + b;
	}
};
class SubOperator :public Operator
{
	int GetResult() override
	{
		return a - b;
	}
};
class MulOperator :public Operator
{
	int GetResult() override
	{
		return a * b;
	}
};
class DivideOperator :public Operator
{
	int GetResult() override
	{
		if (b != 0)
		{
			return a / b;
		}
		else
		{
			throw "除数不能为零";
		}
	}
};
class OperatorFactory
{
public:
	virtual Operator* Createoperator()=0;
};

class AddFactory : public OperatorFactory
{
public:
	Operator* Createoperator() override
	{
		return new AddOperator();
	}
};
class SubFactory : public OperatorFactory
{
public:
	Operator* Createoperator() override
	{
		return new SubOperator();
	}
};
class MulFactory : public OperatorFactory
{
public:
	Operator* Createoperator() override
	{
		return new MulOperator();
	}
};
class DivideFactory : public OperatorFactory
{
public:
	Operator* Createoperator() override
	{
		return new DivideOperator();
	}
};
int main()
{
	OperatorFactory* factory = new DivideFactory();
	Operator *oper= factory->Createoperator();
	oper->a = 6;
	oper->b = 3;
	int r = oper->GetResult();
	std::cout << r;
}

抽象工厂模式

当工厂模式中的要生成类的种类很多时,可以使用抽象模式进一步改造,本质是对它们进行分类。
比如下面例子中要产生MYSQL插入用户数据的类,向MYSQL插入水果数据的类,向SQLserver插入用户数据的类,向SQLserver插入水果数据的类。可以分为向MYSQL和SQLserver插入数据的类,再在两个类中生成插入用户数据和水果数据的类。
这里没有画出用户类,水果类的关系
img

#include<iostream>
using namespace std;
class User
{
public:
	string name;
	int age;
	User(string name, int age) :name(name), age(age) {};
};
class UserInterface
{
public:
	virtual void insert(User* user) = 0;
};
class SQLServerUser :public UserInterface
{
public:
	void insert(User* user) override
	{
		cout << "实现向SQLserver的user表中插入数据" << user->name<<" " << user->age << "\n";
	}
};
class MYSQLUser :public UserInterface
{
public:
	void insert(User* user) override
	{
		cout << "实现向MYSQL的user表中插入数据" << user->name << " " << user->age << "\n";
	}
};

class Fruit
{
public:
	string name;
	int price;
	Fruit(string name, int price) :name(name), price(price) {};
};
class FruitInterface
{
public:
	virtual void insert(Fruit fruit) = 0;
};
class SQLServerFruit :public FruitInterface
{
public:
	void insert(Fruit fruit) override
	{
		cout << "实现向SQLserver的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n";
	}
};
class MYSQLFruit :public FruitInterface
{
public:
	void insert(Fruit fruit) override
	{
		cout << "实现向MYSQL的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n";
	}
};

class FactoryInterface
{
public:
	virtual UserInterface* CreateUser() = 0;
	virtual FruitInterface* CreateFruit() = 0;
};
class SQLserverFactory :FactoryInterface
{
public:
	static UserInterface* CreaterUser()
	{
		return new SQLServerUser();
	}
	static FruitInterface* CreteFruit()
	{
		return new SQLServerFruit();
	}
};
class MYSQLFactory :FactoryInterface
{
public:
	static UserInterface* CreaterUser()
	{
		return new MYSQLUser();
	}
	static FruitInterface* CreteFruit()
	{
		return new MYSQLFruit();
	}
};
int main()
{
	//UserInterface* user = SQLserverFactory::CreaterUser();
	UserInterface* user = MYSQLFactory::CreaterUser();
	user->insert(new User("小明",16));
}

但是每增加一种具体的需求,需要增加多个类,可以使用简单工厂来改进抽象工厂。之后还可以利用反射进一步改进。

#include<iostream>
#include<vector>
using namespace std;
class User
{
public:
	string name;
	int age;
	User(string name, int age) :name(name), age(age) {};
};
class UserInterface
{
public:
	virtual void insert(User* user) = 0;
};
class SQLServerUser :public UserInterface
{
public:
	void insert(User* user) override
	{
		cout << "实现向SQLserver的user表中插入数据" << user->name<<" " << user->age << "\n";
	}
};
class MYSQLUser :public UserInterface
{
public:
	void insert(User* user) override
	{
		cout << "实现向MYSQL的user表中插入数据" << user->name << " " << user->age << "\n";
	}
};

class Fruit
{
public:
	string name;
	int price;
	Fruit(string name, int price) :name(name), price(price) {};
};
class FruitInterface
{
public:
	virtual void insert(Fruit fruit) = 0;
};
class SQLServerFruit :public FruitInterface
{
public:
	void insert(Fruit fruit) override
	{
		cout << "实现向SQLserver的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n";
	}
};
class MYSQLFruit :public FruitInterface
{
public:
	void insert(Fruit fruit) override
	{
		cout << "实现向MYSQL的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n";
	}
};
class DataAccess
{
public: 
	const static int database=0;//0 sqlserver,1 mysql
	static UserInterface* CreaterUser()
	{
		UserInterface* instance=nullptr;
		switch (database)
		{
		case 0:
			instance=new SQLServerUser();
		case 1:
			instance=new MYSQLUser();
		}
		return instance;
	}

	static FruitInterface* CreteFruit()
	{
		FruitInterface* instance = nullptr;
		switch (database)
		{
		case 0:
			instance = new SQLServerFruit();
		case 1:
			instance = new MYSQLFruit();
		}
		return instance;
	}
};
int main()
{
	UserInterface* user =DataAccess::CreaterUser();
	user->insert(new User("小明",16));
}

建造者模式

当对象构建过程稳定,但内部细节可能变化时使用。使得对象构建与表示分离,只需要指定构造类型就可以创建不同的表示
主要包含产品类(产品有不同的表现),建造者(负责为构造产品提供一组抽象接口),具体构造者(实现抽象接口),指导者(构建使用建造者接口的对象)
img

#include<iostream>
#include<vector>
using namespace std;
//产品类
class Soup
{
public:
	vector<string> ingredients;
	void Add(string in)
	{
		cout << "加了点" << in << '\n';
		ingredients.push_back(in);
	}
	void Show()
	{
		cout << "这个汤的配料有" << '\n';
		for (auto i = ingredients.begin(); i != ingredients.end(); ++i)
		{
			cout << *i << " ";
		}
	}
};
//构造者
class CookSoup
{
public:
	virtual void AddVegetable() = 0;
	virtual void AddWater() = 0;
	virtual void AddSeasoning() = 0;
};
//具体构造者
class CookTomotoSoup :public CookSoup
{
public:
	Soup* soup;
	CookTomotoSoup(Soup* soup)
	{
		this->soup = soup;
	}
	void AddVegetable()
	{
		soup->Add("西红柿");
	}
	void  AddWater()
	{
		soup->Add("水");
	}
	void AddSeasoning()
	{
		soup->Add("盐");
	}
	Soup *Get()
	{
		return soup;
	}
};
//指导者
class Director
{
public:
	void cook(CookSoup* cooksoup)
	{
		cooksoup->AddWater();
		cooksoup->AddVegetable();
		cooksoup->AddSeasoning();
	}
};
int main()
{
	Director* d = new Director();
	Soup *soup = new Soup();
	CookTomotoSoup* s = new CookTomotoSoup(soup);

	d->cook(s);
	Soup *dish = s->Get();
	dish->Show();
}

原型模式

不通过构造函数,用一个对象初始化另一个对象。实现方法是在原型类中声明克隆自己的接口(c++中就是虚函数),在具体实现类中实现这一接口。

主要是为了多态,使用父类指针克隆子类

#include<iostream>
using namespace std;
class WorkExperience
{
public:
	string company;
};

class Resume
{
protected:
	string name;
	int age;
	WorkExperience workExperience;
public:
	virtual void display() = 0;
	virtual Resume* clone() = 0;
};

class ConcreteResume1:public Resume
{
public:
	ConcreteResume1(string name, int age,string company)
	{
		this->name = name;
		this->age = age;
		this->workExperience.company = company;
	}
	ConcreteResume1(ConcreteResume1& resume)
	{
		this->name = resume.name;
		this->age = resume.age;
	}
	void setName(string name)
	{
		this->name = name;
	}
	void setAge(int age)
	{
		this->age = age;
	}
	void setWorkExperience(string company)
	{
		this->workExperience.company = company;
	}
	void display() override
	{
		cout << "姓名" << name << "年龄" << age << workExperience.company<< '\n';
	}

	ConcreteResume1* clone() override
	{
		return new ConcreteResume1(*this);
	}
};
int main()
{
	Resume *resume1 = new ConcreteResume1("小华", 20,"大米");
	ConcreteResume1 *resume3 = resume1.clone();
	resume3->display();
}

单例模式

当某个类只能实例化一个对象时使用

所有拷贝构造函数要delete掉
默认构造函数要设为private
使用静态变量保存实例化的对象,并提供函数返回这个对象

根据对象实例化时机的不同分为
懒汉模式:只有在使用时才实例化对象
饿汉模式:代码初始化时就实例化对象

结构性模式

适配器模式

主要用于补救,当不容易直接修改代码时,来统一调用的接口,STL中就有适配器
img

//假设这里只支持out,不支持SpecialOut
#include<iostream>
using namespace std;
class Normal
{
public:
	static void out()
	{
		cout << "通用的输出" << '\n';
	}
};
class Special
{
public:
	static void SpecialOut()
	{
		cout << "特别的输出" << '\n';
	}
};
class Adapte :public Normal
{
public:
	static void out(Special *special)
	{
		special->SpecialOut();
	}
};
int main()
{
	//假设这里只支持out
	Normal::out();
	Adapte::out(new Special());
}

代理模式

代替一个对象对另一个对象访问,用在:

  • 远程代理
  • 虚拟代理:当需要创建开销很大的对象时,通过代理存放对象,来逐步创建
  • 安全代理:控制访问权限
  • 智能指引:在调用对象时,处理一些额外的事

相比适配器模式:都是在原来之上加了一层。适配器模式是原接口不能使用,转换为能使用的新接口,代理模式是和原接口一样,只是想隐藏原接口,并且通过代理可以额外做其它的事。
这里省略了target类的关系
img

#include<iostream>
#include<fstream>
using namespace std;
 class GiveInterface
{
public:
	virtual void Givemoney()=0;
	virtual void GiveGift() = 0;
};
 class Target
 {
 public:
	 string name;
	 Target(string name) :name(name) {};
 };
 class Pursuit :public GiveInterface
 {
 public:
	 Target *person;
	 string myname;
	 Pursuit(Target* person,string myname)
	 {
		 this->person = person;
		 this->myname = myname;
	 }
	 void Givemoney()
	 {
		 cout << "送钱给" <<person->name<< '\n';
	 }
	 void GiveGift()
	 {
		 cout << "送礼物给" << person->name << '\n';
	 }
};
 class Proxy :public GiveInterface
 {
 public:
	 Pursuit *pursuit;
	 Proxy(Target* person,string client)
	 {
		 this->pursuit = new Pursuit(person,client);
	 }
	 void Givemoney()
	 {
		 cout << "代表" << pursuit->myname << ",";
		 pursuit->Givemoney();
	 }
	 void GiveGift()
	 {
		 cout << "代表" << pursuit->myname << ",";
		 pursuit->GiveGift();
	 }
 };
int main()
{
	Target t("花花");
	string client = "李华";
	Proxy p(&t,client);
	p.GiveGift();
	p.Givemoney();
}

代表李华,送礼物给花花
代表李华,送钱给花花

外观(门面)模式

为子系统一组接口,提供一个统一的高层接口

  • 在设计初期,在数据访问和业务逻辑和表示层各层之间建立这样的类
  • 在维护复杂老系统时建立这样的类来提供更清晰的接口

与代理的区别是:代理只代表一个对象,而这个对象不允许直接被访问。外观是代表一个系统,通过外观对象访问子系统各个对象
下面例子的子系统包含door类和people类两个类,在之上提供一个更高层的GoHome类
img

#include<iostream>
using namespace std;
class Door
{
public:
	void open()
	{
		cout << "开门" << '\n';
	}
	void close()
	{
		cout << "关门" << '\n';
	}
};
class People
{
public:
	void walk()
	{
		cout << "走……" << '\n';
	}
};

class GoHome
{
public:
	Door *door;
	People *people;
	GoHome()
	{
		door = new Door();
		people = new People();
	}
	void start()
	{
		door->open();
		people->walk();
		door->close();
	}
};
int main()
{
	GoHome* gohome = new GoHome();
	gohome->start();
}

桥接模式

当实现可以有多角度去分类时,只用继承会增加大量类,这时用桥接模式:让多角度的类独立出来,使得每种类的变化不会影响到其它类。
如下例,不同手机有不同的APP,比如只靠继承,手机品牌1要实现手机品牌1的游戏app,社交app,手机品牌2要实现手机品牌1的游戏app,社交app会产生多个类。
用桥接分别实现手机品牌类和APP类,再通过手机聚合APP,像桥一样接起来。
img

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

class APP
{
public:
	virtual void RUN() = 0;
};
class GameAPP:public APP
{
public:
	void RUN()
	{
		cout << "游戏启动" << '\n';
	}
};
class SocialAPP :public APP
{
public:
	void RUN()
	{
		cout << "社交应用启动" << '\n';
	}
};
class Phone
{
public:
	vector<APP*> app;
	virtual void RUN(int appID)=0;
};
class MIPhone:public Phone
{
public:
	void RUN(int appID) override
	{
		app[appID]->RUN();
	}
};
int main()
{
	MIPhone *phone = new MIPhone();

	phone->app.push_back(new SocialAPP());
	phone->app.push_back(new GameAPP());

	phone->RUN(0);
}

装饰模式

可以有选择和有顺序的为已有功能动态添加更多功能,比生成子类更灵活
当需要满足类一些特殊功能时,不增加原有类的复杂度,而把功能封装为一个类,用这个功能类包装需要修饰的对象。
下例中Todo类装饰Myday,继承它原有的功能,并增加其它功能
img

#include<iostream>

class Myday
{
public:
	std::string date;
	Myday(){}
	Myday(std::string date)
	{
		this->date = date;
	}
	virtual void ShowMyLife()
	{
		std::cout << date  << "我的生活记录"<< '\n';
	}
};

class Todo:public Myday
{
public:
	Myday *myday;
	void doThing(Myday *myday) 
	{
		this->myday = myday;
	}
	
	void ShowMyLife()
	{
		myday->ShowMyLife();
	}
};
class ToSleep :public Todo
{
public:
	void ShowMyLife() override
	{
		Todo::ShowMyLife();
		std::cout << "睡了一觉" << '\n';
		
	}
};
class ToEat :public Todo
{
public:
	void ShowMyLife() override
	{
		Todo::ShowMyLife();
		std::cout << "吃了一顿" << '\n';
	}
};
int main()
{
	Myday i("7月23日");
	ToSleep *sleep = new ToSleep();
	ToEat* eat = new ToEat();

	eat->doThing(&i);
	sleep->doThing(eat);
	sleep->ShowMyLife();
}

享元模式

当需要创建多个对象,而这些对象又有很多相同的参数,可以通过享元模式,只用实例化几个对象,而把不同的参数保存在外部的对象中,这样可以节省内存等开销。
比如有不同网站类型,但同一网站只有用户有区别,可以把用户单独出来,相同类型网站都是相同的,只要指定不同的用户
img

#include<iostream>
#include<map>
using namespace std;
class User
{
public:
	string name;
	User(string name) :name(name) {};
};
class WebSite
{
public:
	virtual void Use(User user) = 0;
};
class ConcreteWebSite :public WebSite
{
public:
	string type;
	ConcreteWebSite(string type):type(type){}
	void Use(User user) override
	{
		cout << "关于" << type << "设置使用。";
		cout << user.name << "使用"<<'\n';
	}
};
class WebSiteFactory
{
public:
	map<string, ConcreteWebSite*> factory;
	ConcreteWebSite* GetWebSIte(string type)
	{
		
		if(factory.find(type)==factory.end())
		{
			factory.insert({ type,new ConcreteWebSite(type) });
		}
		return factory[type];
	}
};
int main()
{
	//user相当于外部信息
	User user1("小明");
	User user2("小红");
	User user3("小王");
	//下面只用实例化两个对象,小明和小红共用一个电子商城
	WebSiteFactory *webFactory = new WebSiteFactory();

	ConcreteWebSite *web1=webFactory->GetWebSIte("电子商城");
	web1->Use(user1);

	ConcreteWebSite* web2 = webFactory->GetWebSIte("电子商城");
	web2->Use(user2);

	ConcreteWebSite* web3 = webFactory->GetWebSIte("视频网站");
	web3->Use(user3);
}

组合模式

用于对象具有树形层次结构时
img

#include<iostream>
#include<list>
using namespace std;
class Component
{
public:
	string name;
	Component(string name) :name(name) {};
	virtual void add(Component* component) = 0;
	virtual void remove(Component* component) = 0;
	virtual void display() = 0;
};
class Leaf: public Component
{
public:
	Leaf(string name) :Component(name) {};
	void add(Component* component)
	{
		cout << "叶结点没有子节点" << '\n';
	}
	void remove(Component* component)
	{
		cout<< "叶结点没有子节点" << '\n';
	}
	void display()
	{
		cout << this->name << '\n';
	}
};
class Twigs :public Component
{
public:
	Twigs(string name) :Component(name) {};
	list<Component*> child;
	void add(Component* component)
	{
		child.push_back(component);
	}
	void remove(Component* component)
	{
		child.remove(component);
	}
	void display()
	{
		cout << this->name << '\n';
		for (auto i=child.begin();i!=child.end();++i)
		{
			(*i)->display();
		}
	}
};
int main()
{
	Twigs root("根节点0");
	Twigs child1("子节点1");
	Leaf child2("叶节点2");
	Leaf child3("叶节点3");
	Leaf child4("叶节点4");
	child1.add(&child3);
	child1.add(&child4);
	root.add(&child1);
	root.add(&child2);
	root.display();

	child1.remove(&child4);
	root.display();
}

行为模式

观察者模式

当一种对象变化时,需要改变其它对象的状态时使用。
其它对象监听某种改变(其实就是定义一个通知自己的函数),当有改变时该对象调用这个函数。
但实际中多种类通知自己的接口都不统一,所以有委托的特性(在C#等中)。
下例中,每个学生子类都定义了Notify函数,监视者类是老师的子类,当其状态变为“老师来了”,他就调用学生对象的Notify函数通知学生
img

#include<iostream>
#include<vector>
using namespace std;
class Student
{
public:
	string name;
	string state;
	virtual void Notify() {};
};
class TalkStudent :public Student
{
public:
	TalkStudent(string name)
	{
		this->name = name;
		this->state = "侃侃而谈";
	}
	void StopTalk()
	{
		cout << this->name << "停止说话" << '\n';
	}
	virtual void Notify() override
	{
		this->StopTalk();
		this->state = "认真学习";
		cout << this->name << this->state << '\n';
	}
};
class PlayStudent :public Student
{
public:
	PlayStudent(string name)
	{
		this->name = name;
		this->state = "愉快玩耍";
	}
	void StopPlay()
	{
		cout << this->name << "停止玩耍" << '\n';
	}
	void Notify() override
	{
		this->StopPlay();
		this->state = "认真学习";
		cout << this->name << this->state << '\n';
	}
};
class TeacherSubject
{
public:
	string state;
	vector<Student*> *students;
	virtual void Add(Student* student) = 0;
	virtual void Remove(Student* student) = 0;
	virtual void Notify() = 0;
};
class MonitorTeacher :public TeacherSubject
{
public:
	MonitorTeacher()
	{
		this->students = new vector<Student*>();
	}
	void Add(Student* student) override
	{
		students->push_back(student);
	}
	void Remove(Student* student) override
	{
		for (auto i = students->begin(); i != students->end(); ++i)
		{
			if ((*i)->name == student->name)
			{
				students->erase(i);
			}
		}
	}
	void Notify() override
	{
		cout << this->state << '\n';
		for (auto i = students->begin(); i != students->end(); ++i)
		{
			(*i)->Notify();
		}
	}
};
int main()
{
	TalkStudent* tStudent = new TalkStudent("小明");
	PlayStudent* pStudent = new PlayStudent("小王");

	MonitorTeacher *monitor = new MonitorTeacher();
	monitor->Add(tStudent);
	monitor->Add(pStudent);

	monitor->state = "老师来了";
	monitor->Notify();
}

模板方法模式

当完成一些过程步骤时是相同的,但具体步骤的细节又是不同时使用。
将相同步骤抽象为模板方法,具体细节由子类具体实现。

#include<iostream>
using namespace std;
class People
{
public:
	virtual void Ready() = 0;
	virtual void Start() = 0;
	void EatTemplate()
	{
		Ready();
		Start();
	}
};
class XiaoMing :public People
{
public:
	void Ready()override
	{
		cout << "端起碗,拿起筷子" << '\n';
	}
	void Start()override
	{
		cout << "大口吃" << '\n';
	}
};
class XiaoBai :public People
{
public:
	void Ready()override
	{
		cout << "放下碗,拿起勺子" << '\n';
	}
	void Start()override
	{
		cout << "挑着吃" << '\n';
	}
};
int main()
{
	XiaoMing ming;
	ming.EatTemplate();

	XiaoBai bai;
	bai.EatTemplate();
}

命令模式

将请求一个操作的对象与执行一个操作的对象分隔开,使得可以对请求进行记录,撤销等操作。
img

#include<iostream>
#include<list>
using namespace std;
class Receiver
{
public:
	void ExcuteCommand1()
	{
		cout << "执行命令1" << '\n';
	}
	void ExcuteCommand2()
	{
		cout << "执行命令2" << '\n';
	}
};
class Command
{
public:
	Receiver* receiver;
	Command(Receiver* receiver)
	{
		this->receiver = receiver;
	}
	virtual void Action() = 0;
};
class Command1 :public Command
{
public:
	Command1(Receiver* receiver):Command(receiver){}
	void Action()
	{
		receiver->ExcuteCommand1();
	}
};
class Command2 :public Command
{
public:
	Command2(Receiver* receiver) :Command(receiver) {}
	void Action()
	{
		receiver->ExcuteCommand2();
	}
};
class Invoker
{
public:
	list<Command*> command;
	void AddCommand(Command* c)
	{
		command.push_back(c);
	}
	void RemoveCommand(Command* c)
	{
		command.remove(c);
	}
	void Notify()
	{
		for (auto i : command)
		{
			i->Action();
		}
	}
};
int main()
{
	Receiver *receiver = new Receiver();
	Command1 *c1 = new Command1(receiver);
	Command2* c2 = new Command2(receiver);

	Invoker *i = new Invoker();
	i->AddCommand(c2);
	i->AddCommand(c1);

	i->Notify();
}

状态模式

当对象根据不同条件有不同状态时使用。通过不同状态类的局部化,分解过大的条件判断语句。
如下例,需要根据不同时间调整学习的状态,这样需要很多ifelse判断,通过状态模式可以将这些判断分成几个链式连接的对象
img

#include<iostream>
#include<vector>
class State;
class Study;
class InsistState;
class GiveUpState;
class AfternoonState;
class ForenoonState;

using namespace std;
class State
{
public:
	virtual void GetState(Study* s) = 0;
};

class Study
{
public:
	State* currentState;
	int currentTime;
	bool moodGood;
	Study(int time, bool moodGood)
	{
		this->currentTime = time;
		this->moodGood = moodGood;
	}
	void SetState(State* state)
	{
		this->currentState = state;
	}
	void GetState()
	{
		currentState->GetState(this);
	}
};

class GiveUpState :public State
{
	void GetState(Study* s)
	{
		cout << "现在是" << s->currentTime << "点,学习?学个屁!" << '\n';
	}
};
class InsistState :public State
{
	void GetState(Study* s)
	{
		cout << "现在是" << s->currentTime << "点,扶我起来,我还能学" << '\n';
	}
};
class AfternoonState :public State
{
	void GetState(Study* s)
	{
		if (s->currentTime < 24)
		{
			cout << "现在是" << s->currentTime << "点,有点累,但我还能学" << '\n';
		}
		else
		{
			if (s->moodGood == true)
			{
				s->SetState(new InsistState());
				s->GetState();
			}
			else
			{
				s->SetState(new GiveUpState());
				s->GetState();
			}
		}
	}
};
class ForenoonState :public State
{
	void GetState(Study* s)
	{
		if (s->currentTime <= 12)
		{
			cout << "现在是" << s->currentTime << "点,我学的很起劲" << '\n';
		}
		else
		{
			s->SetState(new AfternoonState());
			s->GetState();
		}
	}
};

int main()
{
	int time = 8;
	bool mood = false;
	Study* s = new Study(time, mood);
	s->currentState = new ForenoonState();
	s->GetState();
	while (time != 24)
	{
		time++;
		s->currentTime = time;
		s->GetState();
	}
	
}

职责链模式

可以简化对象之间的相互连接,使请求沿着对象连接的链处理下去
下例中,设置leader的后继是boss,当request无法处理,可以传递给boss
img

#include<iostream>
#include<list>
using namespace std;
class Request
{
public:
	string level;
	string content;
	Request(string content,string level)
	{
		this->content = content;
		this->level = level;
	}
};
class handler
{
public:
	handler* senior;
	virtual void handle(Request* request) = 0;
	void setSussessor(handler* senior)
	{
		this->senior = senior;
	}
};
class leader :public handler
{
public:
	void handle(Request* request) override
	{
		if (request->level == "leader")
		{
			cout << "leader处理了" << request->content << '\n';
		}
		else
		{
			senior->handle(request);
		}
	}
};
class boss :public handler
{
public:
	void handle(Request* request) override
	{
		cout << "boss处理了" << request->content << '\n';
	}
};
int main()
{
	Request request("小明请个假", "boss");

	leader *l = new leader();
	boss* b = new boss();
	l->setSussessor(b);

	l->handle(&request);
}

解释器模式

对语言解释执行

#include<iostream>
#include<map>
using namespace std;
class Express
{
public:
	void Interpret(string context)
	{
		Excute(context[0]);

	}
	virtual void Excute(char key) = 0;
};
class EndSymbol :public Express
{
	void Excute(char key)
	{
		switch(key)
		{
		case '!':
			cout << '\n';
			break;
		case '?':
			cout << '\.';
			break;
		}
	}
};
class Text :public Express
{
	void Excute(char key)
	{
		switch (key)
		{
		case '1':
			cout << "q";
			break;
		case '2':
			cout << 'w';
			break;
		case '3':
			cout << 'e';
			break;
		case '4':
			cout << 'r';
			break;
		case '5':
			cout << 't';
			break;
		case '6':
			cout << 'y';
			break;
		case '7':
			cout << 'u';
			break;
		case '8':
			cout << 'i';
			break;
		}
	}
};
int main()
{
	string context = "!1785?!";
	Express *express;
	while (context.length() != 0)
	{
		if (context[0]=='!' || context[0] == '?')
		{
			express = new EndSymbol();
		}
		else
		{
			express = new Text();
		}
		express->Interpret(context);
		context.erase(0, 1);
	}
}

中介模式

用一个对象封装其它对象间的交互。将各对象网状的通信结构变为中心化的通信,各对象不知其他对象的存在,通过中心化的中介者来协调各对象的通信

#include<iostream>
#include<vector>
using namespace std;
class Colleage;
class Mediator
{
public:
	virtual void Send(Colleage* colleage,string message) = 0;
};
class Colleage
{
public:
	Mediator* mediator;
	int ID;
	virtual void Notify(string message) = 0;
	Colleage(Mediator* mediator,int ID) :mediator(mediator),ID(ID){}
};
class Colleage1 :public Colleage
{
public:
	Colleage1(Mediator* mediator, int ID):Colleage(mediator,ID){}
	void Send(string message)
	{
		mediator->Send(this,message);
	}
	void Notify(string message)
	{
		cout << "Colleage1已经收到了信息" << message << '\n';
	}
};
class Colleage2 :public Colleage
{
public:
	Colleage2(Mediator* mediator, int ID) :Colleage(mediator, ID) {}
	void Send(string message)
	{
		mediator->Send(this, message);
	}
	void Notify(string message)
	{
		cout << "Colleage2已经收到了信息" << message << '\n';
	}
};
class ConcreteMediator:public Mediator
{
public:
	vector<Colleage*> colleages;
	//广播,除了自己
	void Send(Colleage* colleage,string message) override
	{
		for (auto i : colleages)
		{
			if (i->ID != colleage->ID)
			{
				i->Notify(message);
			}
		}
	}
};
int main()
{
	ConcreteMediator* m = new ConcreteMediator();
	Colleage1 *c1 = new Colleage1(m, 1);
	Colleage2* c2 = new Colleage2(m, 2);
	m->colleages.push_back(c1);
	m->colleages.push_back(c2);

	c1->Send("今晚统一行动");
}

访问者模式

使得可以不改变原有对象的情况下定义对其它元素的操作
如下例中不用改变man和woman类,以后对于各种goods商品,定义Cosmetic类,在其内就可以定义好man和woman对不同商品goods的喜欢与否
但是人类这个类必须得相对稳定,不能随便多出man与woman之外多个类。适用于数据结构稳定,算法变化的情况

#include<iostream>
#include<map>
using namespace std;
class Man;
class Woman;
class Goods
{
public:
	virtual void Manreaction() = 0;
	virtual void Womanreaction() = 0;
};
class Cosmetic :public Goods
{
public:
	void Manreaction()override
	{
		cout << "Man does not like"<<'\n';
	}
	void Womanreaction()override
	{
		cout << "Woman likes"<<'\n';
	}
};
class Person
{
public:
	virtual void Accept(Goods* goods) = 0;
};
class Man :public Person
{
public:
	void Accept(Goods* goods) override
	{
		goods->Manreaction();
	}
};
class Woman :public Person
{
public:
	void Accept(Goods* goods) override
	{
		goods->Womanreaction();
	}
};
int main()
{
	Woman *woman=new Woman();
	Man *man=new Man();

	Goods *cosmetic=new Cosmetic();

	woman->Accept(cosmetic);
	man->Accept(cosmetic);
}

策略模式:

不同的算法分别实现同一个接口,并封装起来,通过一个对该接口的引用,可以在使用时让不同算法随意替换。
当要实现一堆算法,算法的实现不同,但目标相同,调用方法相同,为了减少算法实现与使用的耦合,考虑使用。
img

#include<iostream>

class Cash
{
public:
	virtual double getCash(double money) { return 0; }
};

class CashNormal: public Cash
{
public:
	double getCash(double money) override
	{
		return money;
	}
};

class CashDiscount : public Cash
{
public:
	double discount;
	CashDiscount(double discount)
	{
		this->discount = discount;
	}
	double getCash(double money) override
	{
		return money*discount;
	}
};


class CashReturn : public Cash
{
public:
	double condition;
	double r;
	CashReturn(double condition,double r)
	{
		this->condition = condition;
		this->r = r;
	}
	double getCash(double money) override
	{
		if (money >= condition)
		{
			return money -r;
		}
		else
		{
			return money;
		}
	}
};

class AppointCash
{
public:
	Cash* cash;
	AppointCash(int type)
	{
		//简单工厂模式与策略模式的结合
		switch (type)
		{
		case 0:
			this->cash = new CashNormal();
			break;
		case 1:
			this->cash = new CashDiscount(0.5);
			break;
		case 2:
			this->cash = new CashReturn(100,50);
			break;
		}
	}

	double GetResult(double money)
	{
		return cash->getCash(money);
	}
};

int main()
{
	AppointCash *user = new AppointCash(1);
	std::cout << user->GetResult(100);
}

备忘录模式

用于需要撤销操作,恢复原有类的场景。需要有备忘录类,来保存原有类信息。还需要有管理类,来保存备忘录类
img

#include<iostream>
using namespace std;
class Memory
{
public:
	Memory(string word) :word(word){}
	string word;
};
class Document
{
public:
	Document(string word):word(word){}
	string word;
	void getContent()
	{
		cout << this->word<<'\n';
	}
	Memory* Store()
	{
		return new Memory(word);
	}
	void Revoke(Memory* memory)
	{
		this->word = memory->word;
	}
};

class Creater
{
public:
	Memory *memory;
};
int main()
{
	Document d("这是一段话");
	d.getContent();

	Creater* c = new Creater();
	c->memory= d.Store();

	d.word = "修改后的一段话";
	d.getContent();

	d.Revoke(c->memory);
	d.getContent();
}

迭代器模式

提供一种方法顺序访问一个聚合对象中各个元素,而不暴露该对象的内部表示
img

#include<iostream>
#include<vector>

class ConcreteAgreate;
template<typename T>
class ConcreteIterator;
using namespace std;

template<typename T>
class Iterator
{
public:
	virtual T first() = 0;
	virtual T next() = 0;
	virtual bool isEnd() = 0;
	virtual T currentItem() = 0;
};

template<typename T>
class ConcreteIterator :public Iterator<T>
{
private:
	ConcreteAgreate* aggreate;
	int current = 0;
public:
	ConcreteIterator(ConcreteAgreate* aggreate)
	{
		this->aggreate = aggreate;
	}
	T first() override
	{
		return aggreate->items[0];
	}
	T next()override
	{
		current++;
		if (current < aggreate->count())
		{
			return aggreate->items[current];
		}
		else
		{
			return nullptr;
		}
	}
	bool isEnd()override
	{
		if (current >= aggreate->count())
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	T currentItem()override
	{
		return aggreate->items[current];
	}
};
template<typename T>
class Agregate
{
public:
	virtual Iterator<T>* createIterator() = 0;
	virtual int count() = 0;
};

//这个类具体实现人的聚合,其中以字符串string表示一个个人,保存在items中
class ConcreteAgreate :public Agregate<string>
{
public:
	vector<string> items;

	ConcreteIterator<string>* createIterator() override
	{
		return new ConcreteIterator<string>(this);
	}
	void push(string item)
	{
		this->items.push_back(item);
	}
	int count() override
	{
		return this->items.size();
	}
};


int main()
{
	ConcreteAgreate* a = new ConcreteAgreate();
	a->push("李白");
	a->push("苏轼");
	a->push("李清照");
	ConcreteIterator<string>* i =  a->createIterator();//创建一个迭代器
	string item = i->first();
	while (!i->isEnd())
	{
		cout << item << '\n';
		item=i->next();
	}
}
posted @ 2022-08-17 22:03  启林O_o  阅读(83)  评论(0编辑  收藏  举报