栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++设计模式

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++设计模式

简介

在此特别感谢李建中老师!!!

以下面代码为例

一、分解

Shape.h

class Point{
public:
	int x;
	int y;
};

class Line{
public:
	Point start;
    Point end;

	Line(const Point& start, const Point& end){
        this->start = start;
        this->end = end;
    }

};

class Rect{
public:
	Point leftUp;
    int width;
	int height;

	Rect(const Point& leftUp, int width, int height){
        this->leftUp = leftUp;
        this->width = width;
		this->height = height;
    }

};

//增加
class Circle{
public:
    point center;//圆心
    int r;//半径
    
    Circle(const Point& c, int r){
		this->center = c;
		this->r = r;
		
	}
  

};
 


MainForm.cpp

//这里写的伪代码 继承的Form不管他
class MainForm : public Form {
private:
	Point p1;
	Point p2;

    //改变
	vector lineVector;
	vector rectVector;
	//增加圆
	vector circleVector;

public:
	MainForm(){
		//...
	}
protected:

	virtual void onMouseDown(const MouseEventArgs& e);
	virtual void onMouseUp(const MouseEventArgs& e);
	virtual void onPaint(const PaintEventArgs& e);
};


void MainForm::onMouseDown(const MouseEventArgs& e){
	p1.x = e.X;
	p1.y = e.Y;

	//...
	Form::onMouseDown(e);
}

void MainForm::onMouseUp(const MouseEventArgs& e){
	p2.x = e.X;
	p2.y = e.Y;

	if (rdoLine.Checked){
		Line line(p1, p2);
		lineVector.push_back(line);
	}
	else if (rdoRect.Checked){
		int width = abs(p2.x - p1.x);
		int height = abs(p2.y - p1.y);
		Rect rect(p1, width, height);
		rectVector.push_back(rect);
	}
	//增加
	else if (rdoCircle.Checked){
    	Point center=p1;
        int r=sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y)); 
        Circle circle(center,r);
		circleVector.push_back(circle);
	}

	//...
	this->Refresh();

	Form::onMouseUp(e);
}

void MainForm::onPaint(const PaintEventArgs& e){

	//画线
	for (int i = 0; i < lineVector.size(); i++){
		e.Graphics.DrawLine(Pens.Red,
			lineVector[i].start.x, 
			lineVector[i].start.y,
			lineVector[i].end.x,
			lineVector[i].end.y);
	}

	//画矩阵
	for (int i = 0; i < rectVector.size(); i++){
		e.Graphics.DrawRectangle(Pens.Red,
			rectVector[i].leftUp,
			rectVector[i].width,
			rectVector[i].height);
	}

	//憎加
	//画圆
	for (int i = 0; i < circleVector.size(); i++){
		e.Graphics.DrawCircle(Pens.Red,
			circleVector[i].center,
                circleVector[i].r );
	}

	//...
	Form::onPaint(e);
}


二、抽象

Shape.h

采用多态机制

class Shape{
public:
	virtual void Draw(const Graphics& g)=0;
	virtual ~Shape() { }
};


class Point{
public:
	int x;
	int y;
};

class Line: public Shape{
public:
	Point start;
	Point end;

	Line(const Point& start, const Point& end){
		this->start = start;
		this->end = end;
	}

	//实现自己的Draw,负责画自己
	virtual void Draw(const Graphics& g){
		g.DrawLine(Pens.Red, 
			start.x, start.y,end.x, end.y);
	}

};

class Rect: public Shape{
public:
	Point leftUp;
	int width;
	int height;

	Rect(const Point& leftUp, int width, int height){
		this->leftUp = leftUp;
		this->width = width;
		this->height = height;
	}

	//实现自己的Draw,负责画自己
	virtual void Draw(const Graphics& g){
		g.DrawRectangle(Pens.Red,
			leftUp,width,height);
	}

};

//增加圆的数据结构
class Circle : public Shape{
public:
    point center;//圆心
    int r;//半径
    
    Circle(const Point& c, int r){
		this->center = c;
		this->r = r;
		
	}
  
	//实现自己的Draw,负责画自己
	virtual void Draw(const Graphics& g){
		g.DrawCircle(Pens.Red,
			center,r);
	}

};


MainForm.cpp

class MainForm : public Form {
private:
	Point p1;
	Point p2;

	//针对所有形状 统一处理
	vector shapeVector;// shape*指针 是因为动态的机制

public:
	MainForm(){
		//...
	}
protected:

	virtual void onMouseDown(const MouseEventArgs& e);
	virtual void onMouseUp(const MouseEventArgs& e);
	virtual void onPaint(const PaintEventArgs& e);
};


void MainForm::onMouseDown(const MouseEventArgs& e){
	p1.x = e.X;
	p1.y = e.Y;

	//...
	Form::onMouseDown(e);
}

void MainForm::onMouseUp(const MouseEventArgs& e){
	p2.x = e.X;
	p2.y = e.Y;

	if (rdoLine.Checked){
		shapeVector.push_back(new Line(p1,p2));// new 一个堆指针
	}
	else if (rdoRect.Checked){
		int width = abs(p2.x - p1.x);
		int height = abs(p2.y - p1.y);
		shapeVector.push_back(new Rect(p1, width, height));
	}
	//增加
	else if (...){
		Point center=p1;
        int r=sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y)); 
        Circle circle(center,r);
		shapeVector.push_back(circle);
	}

	//...
	this->Refresh();

	Form::onMouseUp(e);
}

void MainForm::onPaint(const PaintEventArgs& e){


	for (int i = 0; i < shapeVector.size(); i++){

		shapeVector[i]->Draw(e.Graphics); //多态调用,各负其责 是line就调用line的Draw  是Rect就调用Rect 的Draw
	}

	//...
	Form::onPaint(e);
}


面向对象设计原则

这个其实就是扩展

一个类不能乱指向

子类继承父类,那肯定是有原因的

不要把不必要的方法public出去,如果只是子类用就protected ,如果是本类用就private

对象组合 比如就是 class a里面放一个 class b

继承 子类父类耦合度过高 就是 父类给子类暴露了太多东西

封装变化点 一侧变化 一侧稳定

这里放的就是具体类型,违背面向对象原则

而这个则就是给了一个抽象接口,符合原则。

其实软件的设计也是借鉴其他行业的原则!!!

模板方法Template Method

早绑定

这里的方法没有采用template_method

template_lib.cpp

//程序库开发人员
class Library{

public:
	void Step1(){
		//...
	}

    void Step3(){
		//...
    }

    void Step5(){
		//...
    }
};

template_app.cpp

//应用程序开发人员
class Application{
public:
	bool Step2(){
		//...
    }

    void Step4(){
		//...
    }
};

int main()
{
	//模拟程序流程
	Library lib();
	Application app();

	lib.Step1();

	if (app.Step2()){
		lib.Step3();
	}

	for (int i = 0; i < 4; i++){
		app.Step4();
	}

	lib.Step5();

}

一个晚的东西调用早的东西就是早绑定

晚绑定

采用 template method 的设计模式—前提是你要有稳定的骨架

程序主流程相对稳定

template_lib.cpp

//程序库开发人员
class Library{
public:
	//稳定 template method
    void Run(){
        
        Step1();

        if (Step2()) { //支持变化 ==> 虚函数的多态调用
            Step3(); 
        }

        for (int i = 0; i < 4; i++){
            Step4(); //支持变化 ==> 虚函数的多态调用
        }

        Step5();

    }
	virtual ~Library(){ }//基类的析构写成虚的  因为如果你 new一个子类出来 你要delete子类的话 如果基类的虚构没有写成虚的,可能子类不一定能调用到自己的析构

protected:
	
	void Step1() { //稳定
        //.....
    }
	void Step3() {//稳定
        //.....
    }
	void Step5() { //稳定
		//.....
	}
    //虚函数支持变化
	virtual bool Step2() = 0;//变化 
    virtual void Step4() =0; //变化
};

template_app.cpp

//应用程序开发人员
//继承库 来进行开发
class Application : public Library {
protected:
	virtual bool Step2(){
		//... 子类重写实现
    }

    virtual void Step4() {
		//... 子类重写实现
    }
};

int main()
	{
	//多态指针
	    Library* pLib=new Application();
	    lib->Run();//这里依然会根据流程来走

		delete pLib;//
	}
}

早的东西调用晚的东西就是晚绑定

红色的代表稳定

蓝色的代表不稳定

策略模式 违背开闭原则
enum Taxbase {
	CN_Tax,
	US_Tax,
	DE_Tax,
	FR_Tax       //更改 违背开闭原则
};

class SalesOrder{
    Taxbase tax;
public:
    double CalculateTax(){
        //...
        
        if (tax == CN_Tax){
            //CN***********
        }
        else if (tax == US_Tax){
            //US***********
        }
        else if (tax == DE_Tax){
            //DE***********
        }
		else if (tax == FR_Tax){  //更改
			//...
		}

        //....
     }
    
};

这里要改动的东西多,同时if else 也消耗性能

符合开闭原则

策略模式

class TaxStrategy{
public:
    virtual double Calculate(const Context& context)=0;
    virtual ~TaxStrategy(){}
};


class CNTax : public TaxStrategy{
public:
    virtual double Calculate(const Context& context){
        /

class House{
    //....
};

class HouseBuilder {
public:
    House* GetResult(){//获得house指针

        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 = ...;//这里面用到house里面的东西
    }
    virtual void BuildPart2(){
        
    }
    virtual void BuildPart3(){
        
    }
    virtual void BuildPart4(){
        
    }
    virtual void BuildPart5(){
        
    }
    
};


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();
    }
};

红色的代表稳定,蓝色的代表变化

这里面就是指

HouseBuilder HouseDirector稳定

StoneHouseBuilder等具体的子类是变化的

单件模式


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;//保证唯一

}






//线程安全版本,但锁的代价过高---因为对于都是读操作的线程是浪费的。
//就是只有35行执行结束了,才会释放锁,其他线程才能到32行 这时候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();//默认的顺序:先分配内存 再调用构造器,再把地址赋值给m_instance  
                                        //reorder之后顺序有可能为:先分配内存 ,把地址赋值给m_instance,再调用构造器  这样就导致读存在问题 因为只是分配了原生的内存,没有执行构造器
        }
    }
    return m_instance;
}








//C++ 11版本之后的跨平台实现 (volatile)
std::atomic Singleton::m_instance;//原子对象
std::mutex Singleton::m_mutex;

Singleton* Singleton::getInstance() {
    Singleton* tmp = m_instance.load(std::memory_order_relaxed);//tmp这个指针乐意屏蔽编译器的reorder
    std::atomic_thread_fence(std::memory_order_acquire);//内存fence (内存的屏障 内存reorder的保护)
    //下面的tmp就不会被reorder了
    if (tmp == nullptr) {
        std::lock_guard lock(m_mutex);//上锁
        tmp = m_instance.load(std::memory_order_relaxed);//1内存
        if (tmp == nullptr) {//
            tmp = new Singleton;//2 构造 不会被reorder一定是先执行它 再执行构造器,再把值返回
            std::atomic_thread_fence(std::memory_order_release);//释放内存fence
            m_instance.store(tmp, std::memory_order_relaxed);//3返回到m_instance
        }
    }
    return tmp;
}


享元模式

class Font {
private:

    //unique object key
    string key;
    
    //object state
    //....
    
public:
    Font(const string& key){
        //...
    }
};
ß

class FontFactory{//共享 把要用的对象放在一个共享池里
private:
    map fontPool;
    
public:
    Font* GetFont(const string& key){

        map::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(){
        //...
    }

};

门面模式

以数据库为例

红色的部分 是稳定的,比如返回数据库对象啊什么的

蓝色部分改变的,比如数据表结构,数据连接方式

代理模式

client.cpp

没有使用代理模式

class ISubject{
public:
    virtual void process();
};


class RealSubject: public ISubject{
public:
    virtual void process(){
        //....
    }
};

class ClientApp{
    
    ISubject* subject;
    
public:
    
    ClientApp(){
        subject=new RealSubject();
    }
    
    void DoTask(){
        //...
        subject->process();
        
        //....
    }
};

proxy.cpp

使用了代理模式

class ISubject{
public:
    virtual void process();
};


//Proxy的设计
class SubjectProxy: public ISubject{
    
    
public:
    virtual void process(){
        //对RealSubject的一种间接访问  就是这里和上面的client.cpp有区别 这里面实际上会比上面的复杂很多 ,用SubjectProxy类进行隔离。
        //....
    }
};

class ClientApp{
    
    ISubject* subject;
    
public:
    
    ClientApp(){
        subject=new SubjectProxy();
    }
    
    void DoTask(){
        //...
        subject->process();
        
        //....
    }
};

适配器

老的东西放在新的里面使用

//目标接口(新接口)
class ITarget{
public:
    virtual void process()=0;
};

//遗留接口(老接口)
class IAdaptee{
public:
    virtual void foo(int data)=0;
    virtual int bar()=0;
};

//遗留类型
class OldClass: public IAdaptee{
    //.... 重写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{ //多继承  // protected 和private继承可以叫做实现继承 就是我没有继承你的接口,但是我用你的实现
               
               
}


int main(){
    IAdaptee* pAdaptee=new OldClass();//旧类对象
    
    
    ITarget* pTarget=new Adapter(pAdaptee);//旧类对象塞进adpater里面产生新类对象
    pTarget->process();
    
    
}

//这些也是用到了adapter
class stack{
    deqeue container;
    
};

class queue{
    deqeue container;
    
};


中介者模式

状态模式

没有使用状态模式
cenum 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(){

    }
};



上面的代码采用了很多if else

使用状态模式
class NetworkState{

public:
    NetworkState* pNext;//指向状态改变后的状态
    virtual void Operation1()=0;
    virtual void Operation2()=0;
    virtual void Operation3()=0;

    virtual ~NetworkState(){}
};

//我们把各个不同state的operation都分别在不同的state类里面实现 这样程序的框架更加明显 也更方便后期代码的添加和修改

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{
    
    static NetworkState* m_instance;
public:
    static NetworkState* getInstance(){
        if (m_instance == nullptr) {
            m_instance = new CloseState();
        }
        return m_instance;
    }

    void Operation1(){
        
        //**********
        pNext = ConnectState::getInstance();
    }
    
    void Operation2(){
        
        //..........
         pNext = OpenState::getInstance();
    }
    
    void Operation3(){
        
        //$$$$$$$$$$
        
    }
};


//
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;
        //...
    }
    
    
    
};

红色的是稳定的

蓝色的是变化的

备忘录Memento

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(mem);

   
    
}

组合模式

#include 
#include 
#include 
#include 

using namespace std;

class Component 
{
public:
    virtual void process() = 0;//统一接口
    virtual ~Component(){}
};

//树节点
class Composite : public Component{
    
    string name;
    list elements; //这里list里面有可能是 Composite 也有可能是 Leaf
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 泛型编程基于模板的多态迭代器 效率要低。

template
class Iterator
{
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool isDone() const = 0;
    virtual T& current() = 0;
};



template
class MyCollection{
    
public:
    
    Iterator GetIterator(){
        //...
    }
    
};

template
class CollectionIterator : public Iterator{
    MyCollection mc;
public:
    
    CollectionIterator(const MyCollection & c): mc(c){ }
    
    void first() override {
        
    }
    void next() override {
        
    }
    bool isDone() const override{
        
    }
    T& current() override{
        
    }
};

void MyAlgorithm()
{
    MyCollection mc;
    
    Iterator iter= mc.GetIterator();
    
    for (iter.first(); !iter.isDone(); iter.next()){//虚函数是运行时多态 效率低于编译时多态(编译时已经把工作做了 就不需要运行的时候再计算函数地址了)
        cout << iter.current() << endl;
    }
    
}


职责链

#include 
#include 

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;//多态指针指向自身 形成链表  这样j
    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;
}

命令模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wdiUH1dO-1634011052671)(https://i.loli.net/2021/10/12/qCp2dU5LtwPXNVF.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCVWcLlO-1634011052671)(https://i.loli.net/2021/10/12/qCoy9gZY2EJVXST.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2euliIy-1634011052671)(https://i.loli.net/2021/10/12/xpYTj2BSG5HbgOM.png)]

#include 
#include 
#include 
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..."< 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();//运行时绑定 用的虚函数而不是模板 ,模板时编译时绑定  这个execute就是receiver的action  receiver就是接受请求的对象 receiver的动作就是invoker的execute

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7REWZLzI-1634011052672)(https://i.loli.net/2021/10/12/Zsd296Mv1eDypAN.png)]

访问器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4NcerPtO-1634011052672)(https://i.loli.net/2021/10/12/unZOfRT8Sbz2a3A.png)]

没有使用了visitor模式
#include 
using namespace std;

class Visitor;


class Element
{
public:
    virtual void Func1() = 0;
    
    virtual void Func2(int data)=0;
    virtual void Func3(int data)=0;
    //...
    
    virtual ~Element(){}
};

class ElementA : public Element
{
public:
    void Func1() override{
        //...
    }
    
    void Func2(int data) override{
        //...
    }
    
};

class ElementB : public Element
{
public:
    void Func1() override{
        //***
    }
    
    void Func2(int data) override {
        //***
    }
    
};

由上面代码可以看出,普通的代码在子类里面添加新的函数之外,基类里面也要写一遍。

使用了visitor模式
#include 
using namespace std;

class Visitor;


class Element
{
public:
    virtual void accept(Visitor& 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   输出 Visitor2 is processing ElementB
    
    ElementA elementA;
    elementA.accept(visitor);//输出 Visitor2 is processing ElementA

    
    return 0;
}

由上面代码可以看出。在Element的结构稳定的时候,就是确定了ElementA 和ElementB后,而ElementA 和ElementB里面的方法要改变的时候就可以采用visitor模式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2tYgjLJ-1634011052673)(https://i.loli.net/2021/10/12/X3HQrwWTjF6Iv8q.png)]红色的是稳定的

蓝色是变化的

Visitor里面有多少个方法取决于Element有多少个子类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3wo8z2o-1634011052674)(https://i.loli.net/2021/10/12/Z9cqnU8TH2Ay6sO.png)]

解析器Interpreter

#include 
#include 
#include 

using namespace std;

class expression {
public:
    virtual int interpreter(map var)=0;
    virtual ~expression(){}
};

//变量表达式
class Varexpression: public expression {
    
    char key;
    
public:
    Varexpression(const char& key)
    {
        this->key = key;
    }
    
    int interpreter(map 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 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 var) override {
        return left->interpreter(var) - right->interpreter(var);
    }
    
};



expression*  analyse(string expStr) {
    
    stack expStack;
    expression* left = nullptr;
    expression* right = nullptr;
    for(int i=0; i 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< 

解析器适用于 简单的文法表示,容易抽象为语法规则的问题。

总结

红色圈起来的用的不多,其他的用的很多

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TbDKFzvY-1634011052678)(https://i.loli.net/2021/10/12/UWg4PY8CI5KEntp.png)]

当我们去总结这些各种模式的时候,我们发现它们也有共同点,就是上图中用红色圈起来的地方,就是用指针实现多态。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3D4S5Aj4-1634011052678)(https://i.loli.net/2021/10/12/gtF9cQGiJXLbPkE.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2WukwPRb-1634011052678)(https://i.loli.net/2021/10/12/WYLgwXiVOdKpCn3.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k64rKnJ0-1634011052679)(https://i.loli.net/2021/10/12/vrnwcUl1ieEjNAY.png)]

最高层次就是忘我啊!

总之:

设计模式不是拿来炫耀的,而是服务于代码原则的 。

先看懂别人的模式,

再自己写模式,

之后忘记模式,通过原则设计自己的模式!
#include

using namespace std;

class expression {
public:
virtual int interpreter(map var)=0;
virtual ~expression(){}
};

//变量表达式
class Varexpression: public expression {

char key;

public:
Varexpression(const char& key)
{
this->key = key;
}

int interpreter(map 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 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 var) override {
    return left->interpreter(var) - right->interpreter(var);
}

};

expression* analyse(string expStr) {

stack expStack;
expression* left = nullptr;
expression* right = nullptr;
for(int i=0; i 

}

void release(expression* expression){

//释放表达式树的节点内存...

}

int main(int argc, const char * argv[]) {

string expStr = "a+b-c+d-e";
map 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< 

}

==解析器适用于 简单的文法表示,容易抽象为语法规则的问题。==

[外链图片转存中...(img-dZ2toZPX-1634011052675)]



[外链图片转存中...(img-aGgoytBG-1634011052675)]



[外链图片转存中...(img-NUBvd0gQ-1634011052676)]

# 总结

[外链图片转存中...(img-JgNBRhJQ-1634011052676)]

[外链图片转存中...(img-6Mf6TpSx-1634011052676)]



[外链图片转存中...(img-IGdYHn5o-1634011052677)]

[外链图片转存中...(img-F6o7HzaV-1634011052677)]

[外链图片转存中...(img-GbOy78vm-1634011052677)]

==红色圈起来的用的不多,其他的用的很多==

[外链图片转存中...(img-TbDKFzvY-1634011052678)]

==当我们去总结这些各种模式的时候,我们发现它们也有共同点,就是上图中用红色圈起来的地方,就是用指针实现多态。==

[外链图片转存中...(img-3D4S5Aj4-1634011052678)]

[外链图片转存中...(img-2WukwPRb-1634011052678)]

[外链图片转存中...(img-wQEksUAf-1634011052679)]

[外链图片转存中...(img-k64rKnJ0-1634011052679)]

最高层次就是忘我啊!

==总之:==

设计模式不是拿来炫耀的,而是服务于代码原则的 。

先看懂别人的模式,

再自己写模式,

之后忘记模式,通过原则设计自己的模式!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317566.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号