设计模式
参考:
《大话设计模式》
爱编程的大丙
设计原则
- 单一职责原则:每个类应仅仅负责一种功能逻辑
- 开放封闭原则:对原有的代码封闭,不能修改。对新的功能开放,可以扩展。在设计时,尽量抽象出以后不会改变的类,之后有新的改动可以通过增加新代码,而不改变原有类的方法实现。比如在客户端类中实现四则运算,每增加一种运算就要修改类,可以将运算中不变的抽象出来,之后每增加新的运算,在此基础上扩展就好。
- 依赖倒转原则:抽象不依赖细节,细节依赖抽象。高层模块与底层模块不应该相互依赖,应该都依赖与一个接口(c++就是抽象类),实现各模块的主要目标是实现这个接口。
- 迪米特(最少知识)原则:每个类应尽量减少自己成员和方法的访问权限。两个类如果不直接通信就不应直接相互作用,如果需要调用另一个类的方法,应该通过第三方调用
- 合成聚合原则:优先使用合成聚合,尽量不要使用类继承
- 里氏代换原则:子类型必须能替换父类型
创建型模式
简单工厂模式
当实例化不同对象,且经常变化时,考虑使用。但是不满足开放封闭原则。
一个抽象运算类,加减乘除四个运算类继承这个抽象类,运算工厂类依赖于抽象运算类,负责根据输入的符号构造具体的四个运算类
#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;
}
工厂模式
简单工厂模式需要修改工厂类,违反开放封闭原则。工厂模式为工厂类抽象一个接口,其子类来分别实现接口,这样运算类与工厂类就互不依赖
#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插入数据的类,再在两个类中生成插入用户数据和水果数据的类。
这里没有画出用户类,水果类的关系
#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));
}
建造者模式
当对象构建过程稳定,但内部细节可能变化时使用。使得对象构建与表示分离,只需要指定构造类型就可以创建不同的表示
主要包含产品类(产品有不同的表现),建造者(负责为构造产品提供一组抽象接口),具体构造者(实现抽象接口),指导者(构建使用建造者接口的对象)
#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中就有适配器
//假设这里只支持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类的关系
#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类
#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,像桥一样接起来。
#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,继承它原有的功能,并增加其它功能
#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();
}
享元模式
当需要创建多个对象,而这些对象又有很多相同的参数,可以通过享元模式,只用实例化几个对象,而把不同的参数保存在外部的对象中,这样可以节省内存等开销。
比如有不同网站类型,但同一网站只有用户有区别,可以把用户单独出来,相同类型网站都是相同的,只要指定不同的用户
#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);
}
组合模式
用于对象具有树形层次结构时
#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函数通知学生
#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();
}
命令模式
将请求一个操作的对象与执行一个操作的对象分隔开,使得可以对请求进行记录,撤销等操作。
#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判断,通过状态模式可以将这些判断分成几个链式连接的对象
#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
#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);
}
策略模式:
不同的算法分别实现同一个接口,并封装起来,通过一个对该接口的引用,可以在使用时让不同算法随意替换。
当要实现一堆算法,算法的实现不同,但目标相同,调用方法相同,为了减少算法实现与使用的耦合,考虑使用。
#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);
}
备忘录模式
用于需要撤销操作,恢复原有类的场景。需要有备忘录类,来保存原有类信息。还需要有管理类,来保存备忘录类
#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();
}
迭代器模式
提供一种方法顺序访问一个聚合对象中各个元素,而不暴露该对象的内部表示
#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();
}
}