这里摘录的不是很全,主要记录了个人认为需要记录的模式
文章目录
创建型模式
建造者模式
Builder设计模式是一种创建型的设计模式,它允许您创建不同类型的对象,而无需暴露对象的创建逻辑。在C++中,Builder设计模式通常由一个抽象Builder类和多个具体Builder类组成,以及一个Director类来协调Builder类的使用。
具体地说,抽象Builder类定义了必须由所有具体Builder类实现的创建对象的接口。具体Builder类实现了这些接口,并提供了构建特定类型对象所需的逻辑。Director类使用Builder类来构建对象,并定义了构建对象的顺序和逻辑。
Builder 模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象
Builder设计模式优点:
- 隐藏对象的创建细节:Builder模式将对象的创建过程封装在一个单独的类中,使客户端代码无需了解对象的创建细节。
- 支持创建不同类型的对象:Builder模式允许您创建不同类型的对象,而无需更改客户端代码。这是因为客户端代码仅与抽象Builder类和Director类交互,而不需要了解具体的Builder实现。
- 支持更好的控制对象的创建过程:Builder模式允许您更好地控制对象的创建过程。通过使用Director类来协调Builder类的使用,您可以确保对象按照正确的顺序创建,并且每个对象都被正确地初始化。
- 简化对象的构建:Builder模式使得构建复杂对象变得更加简单。通过将对象的构建过程分解为多个步骤,并由不同的Builder类来执行这些步骤,您可以更容易地构建复杂的对象。
总之,Builder设计模式提供了一种灵活、可扩展和可维护的方式来构建不同类型的对象。它允许您隐藏对象的创建细节,并支持更好地控制对象的创建过程。
class Car {
public:
void setBrand(const std::string& brand) {
m_brand = brand;
}
void setModel(const std::string& model) {
m_model = model;
}
void setYear(int year) {
m_year = year;
}
private:
std::string m_brand;
std::string m_model;
int m_year;
};
class CarBuilder {
public:
virtual ~CarBuilder() {}
virtual void buildBrand() = 0;
virtual void buildModel() = 0;
virtual void buildYear() = 0;
virtual Car* getCar() = 0;
};
class SportsCarBuilder : public CarBuilder {
public:
SportsCarBuilder() {
m_car = new Car();
}
void buildBrand() override {
m_car->setBrand("Ferrari");
}
void buildModel() override {
m_car->setModel("458 Italia");
}
void buildYear() override {
m_car->setYear(2015);
}
Car* getCar() override {
return m_car;
}
private:
Car* m_car;
};
class SUVBuilder : public CarBuilder {
public:
SUVBuilder() {
m_car = new Car();
}
void buildBrand() override {
m_car->setBrand("Jeep");
}
void buildModel() override {
m_car->setModel("Grand Cherokee");
}
void buildYear() override {
m_car->setYear(2020);
}
Car* getCar() override {
return m_car;
}
private:
Car* m_car;
};
class Director {
public:
Director(CarBuilder* builder) : m_builder(builder) {}
Car* construct() {
m_builder->buildBrand();
m_builder->buildModel();
m_builder->buildYear();
return m_builder->getCar();
}
private:
CarBuilder* m_builder;
};
int main() {
SportsCarBuilder sportsCarBuilder;
Director director(&sportsCarBuilder);
Car* sportsCar = director.construct();
SUVBuilder suvBuilder;
director = Director(&suvBuilder);
Car* suv = director.construct();
// use sportsCar and suv
}
结构型模式
Adapter模式
Adapter设计模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。在C++中,Adapter通常以类的形式实现,它包装了一个已有的类并将其接口转换成目标接口。
Adapter设计模式通常包含以下几个组件:
- 目标接口:客户端所期望的接口,Adapter将已有类的接口转换成目标接口。
- 已有类:需要被适配的类。
- Adapter:将已有类的接口转换成目标接口的类。
// 目标接口
class TargetInterface {
public:
virtual void request() = 0;
};
// 已有类
class ExistingClass {
public:
void specificRequest() {
// 原有的实现
}
};
// Adapter
class Adapter : public TargetInterface {
private:
ExistingClass* existing;
public:
Adapter(ExistingClass* existing) {
this->existing = existing;
}
void request() {
existing->specificRequest();
}
};
装饰者(decorator)模式
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。不改变接口的前提下,增强所考虑的类的性能
何时使用
- 需要扩展一个类的功能,或给一个类增加附加责任。
- 需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
- 需要增加一些基本功能的排列组合而产生的非常大量的功能。
他的特点是
- 被拓展功能的类和装饰者类是继承同一接口的,也就是处于同一级,使装饰者可以完整得到被拓展功能类的原先功能
- 装饰者中又包裹了一个被拓展功能类的指针,这样就可以在装饰者自身的动作函数中还原被拓展功能类原先的功能的同时,增加新的功能。
- 在实际运用中实例化装饰者类,实现增加了功能的对象
往往不同的场合会生成不同格式的日志内容,比如有json的,xml的,表格的各种形式,如果用继承的方式就需要在打印日志的类下不停的派生各种子类,然后重载日志输出接口,这样类的复杂度越来越高。此时如果用装饰者,可以需要什么模式的时候就装饰什么。
#include<iostream>
using namespace std;
class log { //整个日志类
public:
virtual void log_out(string filename, string value) {
cout<<"输出日志"<<value<<"到"<<filename<<"文件"<<endl;
}
};
class errlog:public log { //错误日志输出类
public:
void log_out(string filename, string value) {
cout<<"输出错误日志"<<value<<"到"<<filename<<"文件"<<endl;
}
};
class debuglog:public log { //debug日志输出类
public:
void log_out(string filename, string value) {
cout<<"输出debug日志"<<value<<"到"<<filename<<"文件"<<endl;
}
};
class decoratorlog:public log {//日志输出装饰器
public:
log *m_logout;
decoratorlog() {}
decoratorlog(log *logout) {
this->m_logout = logout;
}
void log_out(string filename, string value) {
cout<<"输出debug日志"<<value<<"到"<<filename<<"文件"<<endl;
}
};
class jsondecorator:public decoratorlog {//json日志输出装饰器
public:
jsondecorator(log *logout) {
this->m_logout = logout;
}
void log_out(string filename, string value) {
cout<<"value进行了json转换"<<endl; //装饰器的作用,也就是需要扩充的新功能需求
m_logout->log_out(filename,value); //调用到原先的接口
}
};
class xmldecorator:public decoratorlog {//json日志输出装饰器
public:
xmldecorator(log *logout) {
this->m_logout = logout;
}
void log_out(string filename, string value) {
cout<<"value进行了xml转换"<<endl; //装饰器的作用,也就是需要扩充的新功能需求
m_logout->log_out(filename,value); //调用到原先的接口
}
};
int main() {
log *log1 = new jsondecorator( new debuglog());
log1->log_out("1.json","hello");
log *log2 = new xmldecorator( new errlog());
log2->log_out("1.xml","world");
return 0;
}
/*
value进行了json转换
输出debug日志hello到1.json文件
value进行了xml转换
输出错误日志world到1.xml文件
*/
组合实体(Composite)模式
在 Composite 模式中,有两种类型的对象:叶节点和容器节点。叶节点代表树结构中的最终对象,而容器节点则代表包含其他节点的对象。容器节点可以包含叶节点和其他容器节点,这样就形成了树状结构。
优点如下:
- 简化客户端代码:客户端代码可以像处理单个对象一样处理复杂的树形结构,而不必关心对象是叶节点还是容器节点。
- 易于扩展:可以很容易地向树形结构中添加新的叶节点和容器节点。
- 可以统一处理叶节点和容器节点:在 Composite 模式中,叶节点和容器节点都实现了相同的接口,因此可以统一处理它们。
- 使得设计更加抽象化:通过使用 Composite 模式,可以将复杂的树形结构抽象化,使得设计更加灵活和可维护。
实现
#include <iostream>
#include <vector>
class Component {
public:
virtual void operation() = 0;
virtual ~Component() {}
};
class Leaf : public Component {
public:
void operation() override {
std::cout << "Leaf operation" << std::endl;
}
};
class Composite : public Component {
public:
void operation() override {
std::cout << "Composite operation" << std::endl;
for (auto& component : components_) {
component->operation();
}
}
void add(Component* component) {
components_.push_back(component);
}
private:
std::vector<Component*> components_;
};
int main() {
Leaf leaf;
Composite composite1, composite2;
composite1.add(&leaf);
composite2.add(&composite1);
composite2.operation();
return 0;
}
享元(Flyweight)模式
Flyweight 模式是一种结构型设计模式,它通过共享对象来最小化内存使用和提高性能。在 C++ 中,Flyweight 模式通常使用工厂模式来实现。
使用案例:
- 文字处理器中的字符:在文本编辑器中,每个字符都可以看作是一个对象,但是对于相同的字符,我们并不需要为每个字符都创建一个新的对象。相反,我们可以使用 Flyweight 模式来共享相同的字符对象,从而减少内存使用和提高性能。
- 游戏中的粒子效果:在游戏中,粒子效果通常需要大量的粒子对象。使用 Flyweight 模式,我们可以共享相同的粒子对象,从而减少内存使用和提高性能。
- 电子商务网站中的商品:在电子商务网站中,有很多商品具有相同的属性(如名称、价格等)。使用 Flyweight 模式,我们可以共享相同的商品对象,从而减少内存使用和提高性能。
//Flyweight.h
#ifndef FLYWEIGHT_H
#define FLYWEIGHT_H
#include <string>
#include <list>
typedef std::string STATE;
class Flyweight
{
public:
virtual ~Flyweight(){}
STATE GetIntrinsicState();
virtual void Operation(STATE& ExtrinsicState) = 0;
protected:
Flyweight(const STATE& state)
:m_State(state)
{
}
private:
STATE m_State;
};
class FlyweightFactory
{
public:
FlyweightFactory(){}
~FlyweightFactory();
Flyweight* GetFlyweight(const STATE& key);
private:
std::list<Flyweight*> m_listFlyweight;
};
class ConcreateFlyweight
: public Flyweight
{
public:
ConcreateFlyweight(const STATE& state)
: Flyweight(state)
{
}
virtual ~ConcreateFlyweight(){}
virtual void Operation(STATE& ExtrinsicState);
};
#endif
//Flyweight.cpp
#include "FlyWeight.h"
#include <iostream>
inline STATE Flyweight::GetIntrinsicState()
{
return m_State;
}
FlyweightFactory::~FlyweightFactory()
{
std::list<Flyweight*>::iterator iter1, iter2, temp;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
)
{
temp = iter1;
++iter1;
delete (*temp);
}
m_listFlyweight.clear();
}
Flyweight* FlyweightFactory::GetFlyweight(const STATE& key)
{
std::list<Flyweight*>::iterator iter1, iter2;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
++iter1)
{
if ((*iter1)->GetIntrinsicState() == key)
{
std::cout << "The Flyweight:" << key << " already exits"<< std::endl;
return (*iter1);
}
}
std::cout << "Creating a new Flyweight:" << key << std::endl;
Flyweight* flyweight = new ConcreateFlyweight(key);
m_listFlyweight.push_back(flyweight);
return flyweight;
}
void ConcreateFlyweight::Operation(STATE& ExtrinsicState)
{
}
#include "FlyWeight.h"
int main()
{
FlyweightFactory flyweightfactory;
flyweightfactory.GetFlyweight("hello");
flyweightfactory.GetFlyweight("world");
flyweightfactory.GetFlyweight("hello");
system("pause");
return 0;
}
代理(Proxy)模式
代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问。 代理对象在客服端和目标对象之间起到中介作用。
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
案例
//代理模式:提供一种代理来控制其他对象的访问
#include <iostream>
using namespace std;
class AbstractCommonInterface {
public:
virtual void run() = 0;
};
//下面是操作系统类
class MySystem :public AbstractCommonInterface{
public:
virtual void run() {
cout << "系统启动" << endl;
}
};
//代理: 启动系统必须要权限验证,不是所以的人都可以来启动我的系统,必须要提供用户名和密码
class MySystemProxy :public AbstractCommonInterface {
public:
MySystemProxy(string userName, string password) {
this->mUserName = userName;
this->mPassword = password;
pMySystem = new MySystem;
}
bool checkUserNameAndPassword() {
if (mUserName == "admin" && mPassword == "admin") {
return true;
}
return false;
}
virtual void run() {
if (checkUserNameAndPassword() == true) {
cout << "启动成功" << endl;
this->pMySystem->run();
}
else {
cout << "用户名或者密码错误,权限不足" << endl;
}
}
~MySystemProxy() {
if (pMySystem != NULL) {
delete pMySystem;
}
}
private:
string mUserName;
string mPassword;
MySystem* pMySystem;
};
void test01() {
MySystemProxy* proxy = new MySystemProxy("admin", "admin");
proxy->run();
}
int main()
{
test01();
}
行为模式
状态(state)模式
主要解决问题:
- 当状态数目不是很多的时候,Switch/Case 可能可以搞定。但是当状态数目很多的时候(实际系统中也正是如此),维护一大组的Switch/Case 语句将是一件异常困难并且容易出错的事情。
- 状态逻辑和动作实现没有分离。在很多的系统实现中,动作的实现代码直接写在状态的逻辑当中。这带来的后果就是系统的扩展性和维护得不到保证。
优点:
- 封装了转换规则。
- 枚举可能的状态,在枚举状态之前需要确定状态种类。
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
示例
#include <iostream>
class State {
public:
virtual void handle() = 0;
};
class ConcreteStateA : public State {
public:
void handle() override {
std::cout << "ConcreteStateA handle" << std::endl;
}
};
class ConcreteStateB : public State {
public:
void handle() override {
std::cout << "ConcreteStateB handle" << std::endl;
}
};
class Context {
public:
Context() : state_(nullptr) {}
void setState(State* state) {
state_ = state;
}
void request() {
if (state_) {
state_->handle();
}
}
private:
State* state_;
};
int main() {
Context context;
ConcreteStateA stateA;
ConcreteStateB stateB;
context.setState(&stateA);
context.request();
context.setState(&stateB);
context.request();
return 0;
}
中介者(Mediator)模式
该模式主要用于对象之间的通信。建立中介者完成对象之间的通信
#include <iostream>
#include <string>
#include <vector>
class Colleague;
// 中介者抽象类
class Mediator {
public:
virtual void sendMessage(const std::string& message, const Colleague* colleague) const = 0;
};
// 同事抽象类
class Colleague {
public:
virtual void sendMessage(const std::string& message) const {
m_mediator->sendMessage(message, this);
}
virtual void receiveMessage(const std::string& message) const = 0;
void setMediator(const Mediator* mediator) {
m_mediator = mediator;
}
protected:
const Mediator* m_mediator;
};
// 具体中介者类
class ConcreteMediator : public Mediator {
public:
void addColleague(Colleague* colleague) {
m_colleagues.push_back(colleague);
colleague->setMediator(this);
}
void sendMessage(const std::string& message, const Colleague* colleague) const override {
for (auto c : m_colleagues) {
if (c != colleague) {
c->receiveMessage(message);
}
}
}
private:
std::vector<Colleague*> m_colleagues;
};
// 具体同事类
class ConcreteColleague1 : public Colleague {
public:
void receiveMessage(const std::string& message) const override {
std::cout << "ConcreteColleague1 received message: " << message << std::endl;
}
};
class ConcreteColleague2 : public Colleague {
public:
void receiveMessage(const std::string& message) const override {
std::cout << "ConcreteColleague2 received message: " << message << std::endl;
}
};
int main() {
ConcreteMediator mediator;
ConcreteColleague1 colleague1;
ConcreteColleague2 colleague2;
mediator.addColleague(&colleague1);
mediator.addColleague(&colleague2);
colleague1.sendMessage("Hello, colleague2!");
colleague2.sendMessage("Hi, colleague1!");
return 0;
}
责任链模式
责任链模式属于行为型模式。责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
优点:
- 降低耦合:请求发送者和接收者之间的耦合关系被解除,每个处理器只需要关注自己负责的请求范围,从而使系统更加灵活和可扩展。
- 简化代码:责任链模式使得代码更加简洁和易于维护,每个处理器只需要实现自己的处理逻辑,而无需关注其他部分的实现。
- 支持动态添加或删除处理器:责任链模式允许在运行时动态添加或删除处理器,从而使系统更加灵活和可配置。
示例
class Handler {
public:
Handler(Handler* successor = nullptr) : successor_(successor) {}
virtual ~Handler() {}
virtual void HandleRequest(int request) {
if (successor_) {
successor_->HandleRequest(request);
}
}
protected:
Handler* successor_;
};
class ConcreteHandlerA : public Handler {
public:
void HandleRequest(int request) override {
if (request >= 0 && request < 10) {
std::cout << "Handled by ConcreteHandlerA." << std::endl;
} else if (successor_) {
successor_->HandleRequest(request);
}
}
};
class ConcreteHandlerB : public Handler {
public:
void HandleRequest(int request) override {
if (request >= 10 && request < 20) {
std::cout << "Handled by ConcreteHandlerB." << std::endl;
} else if (successor_) {
successor_->HandleRequest(request);
}
}
};
int main() {
Handler* handler1 = new ConcreteHandlerA();
Handler* handler2 = new ConcreteHandlerB(handler1);
handler2->HandleRequest(5);
handler2->HandleRequest(15);
handler2->HandleRequest(25);
delete handler2;
delete handler1;
return 0;
}