c++23种设计模式(包含8中设计原则)

问题:什么时候用分解,抽象

Mainform(稳定)依赖于抽象shape,实现细节Line和rect依赖于抽象shape


接口声明private,public容易使得客户程序比较依赖这个接口,接口以改变,程序就需要改动,不稳定
对象组合:类A中声明一个类B的对象或指针
一侧变化,一侧稳定
…


不是盲目的用设计模式,在需求发生变化的地方应用



Library* pLib=new Application();pLib是多态指针(声明类型为父类,实现类型为子类)
pLib->Run();
虚函数的动态绑定规则

调用关系发生变化
晚绑定:一个早生成的东西调用晚生成的东西
UML图

** 创建型模式的目的就是封装创建对象的变化;结构型模式封装的是对象之间的组合关系;行为型模式封装的是对象的行为变化。**
模板方法模式
延迟到子类:定义一个虚函数,然后子类实现虚函数,或者子类重写;
Run是一个模板稳定的代码写成非虚函数,变化的代码写成虚函数或者纯虚函数;
模板方法实现的要求就是,必须要有一个稳定的骨架,其中有变化

何谓扩展:继承+多态,继承+虚函数,虚函数的晚绑定机制
策略模式


复用性:编译为二进制代码的复用
**总结: **使用if else/switch语句的情况下可以使用策略模式,除非是性别这种,为了扩展对应变化
class TaxStrategy{
public:
virtual double Calculate(const Context& context)=0;
virtual ~TaxStrategy(){}
};
class CNTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//***********
}
};
class USTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//***********
}
};
class DETax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//***********
}
};
//扩展
//*********************************
class FRTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//.........
}
};
class SalesOrder{
private:
TaxStrategy* strategy;//多态指针
public:
SalesOrder(StrategyFactory* strategyFactory){
this->strategy = strategyFactory->NewStrategy();
}
~SalesOrder(){
delete this->strategy;
}
public double CalculateTax(){
//...
Context context();
double val =
strategy->Calculate(context);
//多态调用,依赖于SalesOrder构造函数中返回
的strategy对象是那个国家的税法
//...
}
};
观察者模式



文件分割器,观察者为进度条,订阅文件分割的进度变化
//多继承推荐方式,继承一个类,后面继承自抽象接口
class MainForm : public Form, public IProgress
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
ConsoleNotifier cn;//控制台观察者
FileSplitter splitter(filePath, number);
splitter.addIProgress(this); //订阅通知,将控制台观察者添加到观察者集合
splitter.addIProgress(&cn); //订阅通知
splitter.split();
splitter.removeIProgress(this);
}
virtual void DoProgress(float value){
progressBar->setValue(value);
}
};
class ConsoleNotifier : public IProgress {
public:
virtual void DoProgress(float value){
cout << ".";
}
};
//抽象的进度表现方式,可以为饼状图,条形图等显示,方便扩展
class IProgress{
public:
virtual void DoProgress(float value)=0;
virtual ~IProgress(){}
};
class FileSplitter
{
string m_filePath;
int m_fileNumber;
// 抽象通知机制,支持多个观察者
List<IProgress*> m_iprogressList;
public:
FileSplitter(const string& filePath, int fileNumber) :
m_filePath(filePath),
m_fileNumber(fileNumber){
}
void split(){
//1.读取大文件
//2.分批次向小文件中写入
for (int i = 0; i < m_fileNumber; i++){
//...
float progressValue = m_fileNumber;
progressValue = (i + 1) / progressValue;
onProgress(progressValue);//发送通知
}
}
void addIProgress(IProgress* iprogress){
m_iprogressList.push_back(iprogress);
}
void removeIProgress(IProgress* iprogress){
m_iprogressList.remove(iprogress);
}
protected:
virtual void onProgress(float value){
List<IProgress*>::iterator itor=m_iprogressList.begin();
while (itor != m_iprogressList.end() )
(*itor)->DoProgress(value); //更新进度条
itor++;
}
}
};

单一职责模式



80行继承(静态特征) 79行组合(动态特征)



继承自父类,有字段,大概率是装饰器模式,继承和组合都在一个类中
//业务操作
class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;
virtual ~Stream(){}
};
//主体类
class FileStream: public Stream{
public:
virtual char Read(int number){
//读文件流
}
virtual void Seek(int position){
//定位文件流
}
virtual void Write(char data){
//写文件流
}
};
class NetworkStream :public Stream{
public:
virtual char Read(int number){
//读网络流
}
virtual void Seek(int position){
//定位网络流
}
virtual void Write(char data){
//写网络流
}
};
class MemoryStream :public Stream{
public:
virtual char Read(int number){
//读内存流
}
virtual void Seek(int position){
//定位内存流
}
virtual void Write(char data){
//写内存流
}
};
//扩展操作
class CryptoStream: public Stream {
//把本来继承的父类编程字段
Stream* stream;//...组合的形式,运行时装配(具有多态性),最后的对象取决于new
public:
CryptoStream(Stream* stm):stream(stm){
//:stream(stm) 是成员初始化列表。它表示,当创建DecoratorStream对象时
//,其成员变量stream应该被初始化为传递给构造函数的参数stm的值
}
virtual char Read(int number){
//额外的加密操作...
stream->Read(number);//读文件流
}
virtual void Seek(int position){
//额外的加密操作...
stream::Seek(position);//定位文件流
//额外的加密操作...
}
virtual void Write(byte data){
//额外的加密操作...
stream::Write(data);//写文件流
//额外的加密操作...
}
};
class BufferedStream : public Stream{
Stream* stream;//...
public:
BufferedStream(Stream* stm):stream(stm){
}
//...
};
void Process(){
//运行时装配
FileStream* s1=new FileStream();
CryptoStream* s2=new CryptoStream(s1);
BufferedStream* s3=new BufferedStream(s1);
BufferedStream* s4=new BufferedStream(s2);
}
桥模式
为什么说指针可以多态



编译时装配和运行时装配理解
Messager *m = new MobileMessagerPerfect();
class Messager{
protected:
MessagerImp* messagerImp;//...
public:
virtual void Login(string username, string password)=0;
virtual void SendMessage(string message)=0;
virtual void SendPicture(Image image)=0;
Messager(MessagerImp* mImp):messagerImp(mImp){
}
virtual ~Messager(){}
};
////平台实现
class MessagerImp{
public:
virtual void PlaySound()=0;
virtual void DrawShape()=0;
virtual void WriteText()=0;
virtual void Connect()=0;
virtual MessagerImp(){}
};
//平台实现 n
class PCMessagerImp : public MessagerImp{
public:
virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
};
//平台实现
class MobileMessagerImp : public MessagerImp{
public:
virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
};
//业务抽象 m
//类的数目:1+n+m
class MessagerLite :public Messager {
MessagerImp* messagerImp;//...
//子类构造函数调用父类构造
public:
virtual void Login(string username, string password){
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->DrawShape();
//........
}
};
class MessagerPerfect :public Messager {
MessagerImp* messagerImp;//...
public:
MessagerPerfect(Messager* messager):messagerImp(messager){
}
virtual void Login(string username, string password){
messagerImp->PlaySound();
//********
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->PlaySound();
//********
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->PlaySound();
//********
messagerImp->DrawShape();
//........
}
};
void Process(){
//运行时装配
//不理解
MessagerImp* mImp=new PCMessagerImp();
Messager *m =new Messager(mImp);
}
工厂方法模式

应对需求的变化,应当将对象的声明创建为抽象类型或者接口,尽量避免具体实现类的声明对象,即为面向接口编程
第16行依然是具体类的实现,仍然依赖具体类,

有改进,但还是编译时依赖,运行时依赖需要用到virtual


FileSpiltter.cpp
//具体类ConcreteProduct
class BinarySplitter : public ISplitter{
};
class TxtSplitter: public ISplitter{
};
class PictureSplitter: public ISplitter{
};
class VideoSplitter: public ISplitter{
};
//具体工厂ConcreteCreator
class BinarySplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new BinarySplitter();
}
};
class TxtSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new TxtSplitter();
}
};
class PictureSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new PictureSplitter();
}
};
class VideoSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new VideoSplitter();
}
};
ISplitterFactory.cpp
//抽象类Product
class ISplitter{
public:
virtual void split()=0;
virtual ~ISplitter(){}
};
//工厂基类Creator
class SplitterFactory{
public:
virtual ISplitter* CreateSplitter()=0;
virtual ~SplitterFactory(){}
};
MainForm.cpp
class MainForm : public Form
{
SplitterFactory* factory;//工厂
public:
//MainForm类中不依赖具体的类,这里构造函数中根据外部传入的具体工厂,
MainForm(SplitterFactory* factory){
this->factory=factory;
}
void Button1_Click(){
//利用虚继承在运行时实现多态new
ISplitter * splitter=
factory-> (); //多态new
splitter->split();
}
};
抽象工厂模式



一系列操作对象之间有相互关联性,比如说sql中command和connection操作;是一系列操作,不能分开
//数据库访问有关的基类
class IDBConnection{//AbstractProductB
};
//AbstractProductA
class IDBCommand{
};
class IDataReader{
};
//AbstractFactory
class IDBFactory{
public:
virtual IDBConnection* CreateDBConnection()=0;
virtual IDBCommand* CreateDBCommand()=0;
virtual IDataReader* CreateDataReader()=0;
};
//支持SQL Server
class SqlConnection: public IDBConnection{
};
class SqlCommand: public IDBCommand{
};
class SqlDataReader: public IDataReader{
};
//ConcreteFactory1
class SqlDBFactory:public IDBFactory{
public:
virtual IDBConnection* CreateDBConnection()=0;
virtual IDBCommand* CreateDBCommand()=0;
virtual IDataReader* CreateDataReader()=0;
};
//支持Oracle
class OracleConnection: public IDBConnection{
};
class OracleCommand: public IDBCommand{
};
class OracleDataReader: public IDataReader{
};
class EmployeeDAO{
IDBFactory* dbFactory;
public:
vector<EmployeeDO> GetEmployees(){
IDBConnection* connection =
dbFactory->CreateDBConnection();
connection->ConnectionString("...");
IDBCommand* command =
dbFactory->CreateDBCommand();
command->CommandText("...");
command->SetConnection(connection); //关联性
IDBDataReader* reader = command->ExecuteReader(); //关联性
while (reader->Read()){
}
}
};
原型模式


通过深克隆

什么时候用:和工厂方法区别,当对象比较复杂的时候,方便实现.直接克隆实现
Prototype.cpp
//抽象类
class ISplitter{
public:
virtual void split()=0;
virtual ISplitter* clone()=0; //通过克隆自己来创建对象
virtual ~ISplitter(){}
};
ConcretePrototype.cpp
//具体类
class BinarySplitter : public ISplitter{
public:
virtual ISplitter* clone(){
//调用拷贝函数生成克隆对象 *this,对象本身
return new BinarySplitter(*this);
}
};
class TxtSplitter: public ISplitter{
public:
virtual ISplitter* clone(){
return new TxtSplitter(*this);
}
};
class PictureSplitter: public ISplitter{
public:
virtual ISplitter* clone(){
return new PictureSplitter(*this);
}
};
class VideoSplitter: public ISplitter{
public:
virtual ISplitter* clone(){
return new VideoSplitter(*this);
}
};
Client.cpp
class MainForm : public Form
{
ISplitter* prototype;//原型对象
public:
MainForm(ISplitter* prototype){
this->prototype=prototype;
}
void Button1_Click(){
//splitter是一个创建的新对象
ISplitter * splitter=
prototype->clone(); //克隆原型
splitter->split();
}
};
构建器模式



类似于创建过程相同,可以创建不同的对象,例如;泡茶和泡咖啡的过程基本差不多,只是原材料不通,可以通过相同的创建过程创建出不同的对象
class House{
//....
//如果在构造函数中调用虚函数,是静态绑定
};
//Builder
class HouseBuilder {
public:
House* GetResult(){
return pHouse;
}
virtual ~HouseBuilder(){}
protected:
House* pHouse;
virtual void BuildPart1()=0;
virtual void BuildPart2()=0;
virtual void BuildPart3()=0;
virtual void BuildPart4()=0;
virtual void BuildPart5()=0;
};
class StoneHouse: public House{
};
class StoneHouseBuilder: public HouseBuilder{
protected:
virtual void BuildPart1(){
//pHouse->Part1 = ...;
}
virtual void BuildPart2(){
}
virtual void BuildPart3(){
}
virtual void BuildPart4(){
}
virtual void BuildPart5(){
}
};
//稳定的 Director
class HouseDirector{
public:
HouseBuilder* pHouseBuilder;
HouseDirector(HouseBuilder* pHouseBuilder){
this->pHouseBuilder=pHouseBuilder;
}
House* Construct(){
pHouseBuilder->BuildPart1();
for (int i = 0; i < 4; i++){
pHouseBuilder->BuildPart2();
}
bool flag=pHouseBuilder->BuildPart3();
if(flag){
pHouseBuilder->BuildPart4();
}
pHouseBuilder->BuildPart5();
return pHouseBuilder->GetResult();
}
};
单例模式

目的是为了优化性能;


class Singleton{
private:
Singleton();
Singleton(const Singleton& other);
public:
static Singleton* getInstance();
static Singleton* m_instance;
};
Singleton* Singleton::m_instance=nullptr;
//单线程可以用
//线程非安全版本
Singleton* Singleton::getInstance() {
if (m_instance == nullptr) {
m_instance = new Singleton();
}
return m_instance;
}
//线程安全版本,但锁的代价过高
Singleton* Singleton::getInstance() {
Lock lock;//加锁,方法结束后开锁
if (m_instance == nullptr) {
m_instance = new Singleton();
}
return m_instance;
}
//不建议使用
//双检查锁,但由于内存读写reorder不安全
Singleton* Singleton::getInstance() {
if(m_instance==nullptr){
Lock lock;
if (m_instance == nullptr) {
m_instance = new Singleton();
}
}
return m_instance;
}
//C++ 11版本之后的跨平台实现 (volatile)
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;
Singleton* Singleton::getInstance() {
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存fence
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
亨元模式

创建对象池,复用对象,降低对象的创建次数

class Font {
private:
//unique object key
string key;
//object state
//....
public:
Font(const string& key){
//...
}
};
ß
//对象池,保障对象的唯一,避免修改对象
class FontFactory{
private:
map<string,Font* > fontPool;
public:
Font* GetFont(const string& key){
map<string,Font*>::iterator item=fontPool.find(key);
//查找到对象
if(item!=footPool.end()){
return fontPool[key];
}
else{
//没有查找到,创建对象并添加到对象池中
Font* font = new Font(key);
fontPool[key]= font;
return font;
}
}
void clear(){
//...
}
};
外观模式





子系统和外部的一种解耦方式.数据访问层就是一个经典的外观设计模式,用一个稳定的接口,隔离变化
代理模式





适配器模式





类适配器用的很少,建议使用对象适配器
//目标接口(新接口)
class ITarget{
public:
virtual void process()=0;
};
//遗留接口(老接口)
class IAdaptee{
public:
virtual void foo(int data)=0;
virtual int bar()=0;
};
//遗留类型
class OldClass: public IAdaptee{
//....
};
//对象适配器
class Adapter: public ITarget{ //继承
protected:
IAdaptee* pAdaptee;//组合
public:
Adapter(IAdaptee* pAdaptee){
this->pAdaptee=pAdaptee;
}
virtual void process(){
int data=pAdaptee->bar();
pAdaptee->foo(data);
}
};
//类适配器
class Adapter: public ITarget,
protected OldClass{ //多继承
}
int main(){
IAdaptee* pAdaptee=new OldClass();
ITarget* pTarget=new Adapter(pAdaptee);
pTarget->process();
}
class stack{
deqeue container;
};
class queue{
deqeue container;
};
中介者模式



数据元素和界面元素之间通过界面绑定(M)
状态模式


state1.cpp
enum NetworkState
{
Network_Open,
Network_Close,
Network_Connect,
};
class NetworkProcessor{
NetworkState state;
public:
void Operation1(){
if (state == Network_Open){
//**********
state = Network_Close;
}
else if (state == Network_Close){
//..........
state = Network_Connect;
}
else if (state == Network_Connect){
//$$$$$$$$$$
state = Network_Open;
}
}
public void Operation2(){
if (state == Network_Open){
//**********
state = Network_Connect;
}
else if (state == Network_Close){
//.....
state = Network_Open;
}
else if (state == Network_Connect){
//$$$$$$$$$$
state = Network_Close;
}
}
public void Operation3(){
}
};
state2.cpp
class NetworkState{
public:
NetworkState* pNext;
virtual void Operation1()=0;
virtual void Operation2()=0;
virtual void Operation3()=0;
virtual ~NetworkState(){}
};
class OpenState :public NetworkState{
static NetworkState* m_instance;
public:
static NetworkState* getInstance(){
if (m_instance == nullptr) {
m_instance = new OpenState();
}
return m_instance;
}
void Operation1(){
//**********
pNext = CloseState::getInstance();
}
void Operation2(){
//..........
pNext = ConnectState::getInstance();
}
void Operation3(){
//$$$$$$$$$$
pNext = OpenState::getInstance();
}
};
class CloseState:public NetworkState{ }
//...
class NetworkProcessor{
NetworkState* pState;
public:
NetworkProcessor(NetworkState* pState){
this->pState = pState;
}
void Operation1(){
//...
pState->Operation1();
pState = pState->pNext;
//...
}
void Operation2(){
//...
pState->Operation2();
pState = pState->pNext;
//...
}
void Operation3(){
//...
pState->Operation3();
pState = pState->pNext;
//...
}
};
备忘录模式




CreateMemento(_)创建备忘录,SetMemento(Memento m)返回备忘录对象,Caretaker使用备忘录
//不改变这个类的封装性
class Memento
{
string state;
//..
public:
Memento(const string & s) : state(s) {}
string getState() const { return state; }
void setState(const string & s) { state = s; }
};
class Originator
{
string state;
//....
public:
Originator() {}
//捕获一个对象的状态 ,存储到备忘录
Memento createMomento() {
Memento m(state);//当前内存状态拍照
return m;
}
void setMomento(const Memento & m) {
state = m.getState();
}
};
int main()
{
Originator orginator;
//捕获对象状态,存储到备忘录
Memento mem = orginator.createMomento();
//... 改变orginator状态
//从备忘录中恢复
orginator.setMomento(memento);
}
组合模式



核心是用是用树形结构解耦了内部对象和外部对象之间的关系

#include <iostream>
#include <list>
#include <string>
#include <algorithm>
using namespace std;
//抽象接口
class Component
{
public:
virtual void process() = 0;
virtual ~Component(){}
};
//树节点
class Composite : public Component{
string name;
list<Component*> elements;
public:
Composite(const string & s) : name(s) {}
void add(Component* element) {
elements.push_back(element);
}
void remove(Component* element){
elements.remove(element);
}
void process(){
//1. process current node
//2. process leaf nodes
for (auto &e : elements)
e->process(); //多态调用(递归调用),将对象的访问放在类内,使得处理一致
}
};
//叶子节点
class Leaf : public Component{
string name;
public:
Leaf(string s) : name(s) {}
void process(){
//process current node
}
};
//客户程序
void Invoke(Component & c){
//...
c.process();
//...
}
int main()
{
Composite root("root");
Composite treeNode1("treeNode1");
Composite treeNode2("treeNode2");
Composite treeNode3("treeNode3");
Composite treeNode4("treeNode4");
Leaf leat1("left1");
Leaf leat2("left2");
root.add(&treeNode1);
treeNode1.add(&treeNode2);
treeNode2.add(&leaf1);
root.add(&treeNode3);
treeNode3.add(&treeNode4);
treeNode4.add(&leaf2);
process(root);
process(leaf2);
process(treeNode3);
}
迭代器模式

集合内部结构可以包含多种数据结构,例如树,队列,栈,数组等
不暴露,就是隔离变化
在c++中过时了,现在较多使用泛型编程STL提供的迭代器,在java中编译时迭代器有使用这种面向对象模式的迭代器,性能较低,不如运行时迭代器(如STL泛型编程所采用的迭代器)
//一面向对象模式实现的迭代器
template<typename T>
class Iterator
{
public:
virtual void first() = 0;
virtual void next() = 0;
virtual bool isDone() const = 0;//末尾元素
virtual T& current() = 0;
};
template<typename T>
class MyCollection{
public:
Iterator<T> GetIterator(){
//...
}
};
template<typename T>
class CollectionIterator : public Iterator<T>{
MyCollection<T> mc;
public:
CollectionIterator(const MyCollection<T> & c): mc(c){ }
void first() override {
}
void next() override {
}
bool isDone() const override{
}
T& current() override{
}
};
void MyAlgorithm()
{
MyCollection<int> mc;
Iterator<int> iter= mc.GetIterator();
for (iter.first(); !iter.isDone(); iter.next()){
cout << iter.current() << endl;
}
}
责任链模式



#include <iostream>
#include <string>
using namespace std;
enum class RequestType
{
REQ_HANDLER1,
REQ_HANDLER2,
REQ_HANDLER3
};
class Reqest
{
string description;
RequestType reqType;
public:
Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
RequestType getReqType() const { return reqType; }
const string& getDescription() const { return description; }
};
class ChainHandler{
//指向自身,形成多态链表
ChainHandler *nextChain;
void sendReqestToNextHandler(const Reqest & req)
{
if (nextChain != nullptr)
nextChain->handle(req);
}
protected:
virtual bool canHandleRequest(const Reqest & req) = 0;
virtual void processRequest(const Reqest & req) = 0;
public:
ChainHandler() { nextChain = nullptr; }
void setNextChain(ChainHandler *next) { nextChain = next; }
void handle(const Reqest & req)
{
//能处理请求
if (canHandleRequest(req))
processRequest(req);
else//当前链表节点不能处理,交给下一个节点处理
sendReqestToNextHandler(req);
}
};
class Handler1 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER1;
}
void processRequest(const Reqest & req) override
{
cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
}
};
class Handler2 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER2;
}
void processRequest(const Reqest & req) override
{
cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
}
};
class Handler3 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER3;
}
void processRequest(const Reqest & req) override
{
cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
}
};
int main(){
Handler1 h1;
Handler2 h2;
Handler3 h3;
h1.setNextChain(&h2);
h2.setNextChain(&h3);
Reqest req("process task ... ", RequestType::REQ_HANDLER3);
h1.handle(req);
return 0;
}

命令模式


在c++中被函数对象仿函数替代,在其他语法Java中较常见
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Command
{
public:
//行为
virtual void execute() = 0;
};
class ConcreteCommand1 : public Command
{
string arg;
public:
//封装成一个一个的对象
ConcreteCommand1(const string & a) : arg(a) {}
void execute() override
{
cout<< "#1 process..."<<arg<<endl;
}
};
class ConcreteCommand2 : public Command
{
string arg;
public:
//封装成一个一个的对象
ConcreteCommand2(const string & a) : arg(a) {}
void execute() override
{
cout<< "#2 process..."<<arg<<endl;
}
};
class MacroCommand : public Command
{
//类似于组合模式
vector<Command*> commands;
public:
void addCommand(Command *c) { commands.push_back(c); }
void execute() override
{
for (auto &c : commands)
{
//运行时动态解析
c->execute();
}
}
};
int main()
{
ConcreteCommand1 command1(receiver, "Arg ###");
ConcreteCommand2 command2(receiver, "Arg $$$");
//一个命令可以包含多个子命令
MacroCommand macro;
macro.addCommand(&command1);
macro.addCommand(&command2);
macro.execute();
}
访问器模式

1.在基类中需要增加方法,在所有子类中都要取增加相应的方法.
存在的条件就是:Element所有类结构要稳定

#include <iostream>
using namespace std;
class Visitor;
class Element
{
public:
//将来添加新的操作,找accept()
virtual void accept(Visitcor& visitor) = 0; //第一次多态辨析
virtual ~Element(){}
};
class ElementA : public Element
{
public:
void accept(Visitor &visitor) override {
visitor.visitElementA(*this);
}
};
class ElementB : public Element
{
public:
void accept(Visitor &visitor) override {
visitor.visitElementB(*this); //第二次多态辨析
}
};
class Visitor{
public:
virtual void visitElementA(ElementA& element) = 0;
virtual void visitElementB(ElementB& element) = 0;
virtual ~Visitor(){}
};
//上面已经设计好了,编译时不改变
//==================================
//扩展1
class Visitor1 : public Visitor{
public:
void visitElementA(ElementA& element) override{
cout << "Visitor1 is processing ElementA" << endl;
}
void visitElementB(ElementB& element) override{
cout << "Visitor1 is processing ElementB" << endl;
}
};
//扩展2
class Visitor2 : public Visitor{
public:
void visitElementA(ElementA& element) override{
cout << "Visitor2 is processing ElementA" << endl;
}
void visitElementB(ElementB& element) override{
cout << "Visitor2 is processing ElementB" << endl;
}
};
int main()
{
Visitor2 visitor;
ElementB elementB;
elementB.accept(visitor);// 重要:double dispatch(二次多态辨析)
ElementA elementA;
//调用过程先去找ElementA的accept(),到19行,visitor是Visitor2,
//到Visitor2中,因为调用的是visitElementA(),跳到60行
elementA.accept(visitor);
return 0;
}

解释器模式




#include <iostream>
#include <map>
#include <stack>
using namespace std;
class Expression {
public:
virtual int interpreter(map<char, int> var)=0;
virtual ~Expression(){}
};
//变量表达式
class VarExpression: public Expression {
char key;
public:
VarExpression(const char& key)
{
this->key = key;
}
int interpreter(map<char, int> var) override {
return var[key];
}
};
//符号表达式
class SymbolExpression : public Expression {
// 运算符左右两个参数
protected:
Expression* left;
Expression* right;
public:
SymbolExpression( Expression* left, Expression* right):
left(left),right(right){
}
};
//加法运算
class AddExpression : public SymbolExpression {
public:
AddExpression(Expression* left, Expression* right):
SymbolExpression(left,right){
}
int interpreter(map<char, int> var) override {
return left->interpreter(var) + right->interpreter(var);
}
};
//减法运算
class SubExpression : public SymbolExpression {
public:
SubExpression(Expression* left, Expression* right):
SymbolExpression(left,right){
}
int interpreter(map<char, int> var) override {
return left->interpreter(var) - right->interpreter(var);
}
};
Expression* analyse(string expStr) {
stack<Expression*> expStack;
Expression* left = nullptr;
Expression* right = nullptr;
for(int i=0; i<expStr.size(); i++)
{
switch(expStr[i])
{
case '+':
// 加法运算
left = expStack.top();
right = new VarExpression(expStr[++i]);
expStack.push(new AddExpression(left, right));
break;
case '-':
// 减法运算
left = expStack.top();
right = new VarExpression(expStr[++i]);
expStack.push(new SubExpression(left, right));
break;
default:
// 变量表达式
expStack.push(new VarExpression(expStr[i]));
}
}
Expression* expression = expStack.top();
return expression;
}
void release(Expression* expression){
//释放表达式树的节点内存...
}
int main(int argc, const char * argv[]) {
string expStr = "a+b-c+d-e";
map<char, int> var;
var.insert(make_pair('a',5));
var.insert(make_pair('b',2));
var.insert(make_pair('c',1));
var.insert(make_pair('d',6));
var.insert(make_pair('e',10));
Expression* expression= analyse(expStr);
int result=expression->interpreter(var);
cout<<result<<endl;
release(expression);
return 0;
}
设计模式总结
目标:管理变化,提高复用!
两种手段:分解vs抽象
八大设计原则:
依赖倒置,开放封闭,单一职责,里氏替换,接口隔离,对象组合优于继承,封装变化点,面向接口编程
重构技法:
1.静态->动态
2.早绑定- >晚绑定
3.继承->组合
4.编译时依赖->运行时依赖
5.紧耦合->松耦合



代码初版慎用模式,当猜测需求的时候,不适合用模式,做外包时,产品的复用不强,不适合
更多推荐

所有评论(0)