c++设计模式

37 篇文章 1 订阅

简介

image-20210929101632610

image-20210929102038290

image-20210929102202129

image-20210929102254456

以下面代码为例

一、分解

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<Line> lineVector;
	vector<Rect> rectVector;
	//增加圆
	vector<Circle> 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<Shape*> 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);
}


面向对象设计原则

image-20210929110509354

image-20210929110925832

image-20210929111353991

image-20210929111337613

这个其实就是扩展

image-20210929111433521

一个类不能乱指向

image-20210929111552066

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

image-20210929111718153

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

image-20210929111850800

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

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

image-20210929112129828

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

image-20210929112231008

image-20210929112311712

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

image-20210929112345448

image-20210929112358470

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

image-20210929112455843

image-20210929112534895

image-20210929112541595

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

image-20210929113116375

模板方法Template Method

image-20210930095041782

image-20210930095053276

image-20210930095103470

image-20210930095112821

image-20210930095120485

image-20210930095303479

image-20210930095420436

早绑定

这里的方法没有采用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();

}

image-20210930100450923

image-20210930100553826

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

晚绑定

采用 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;//
	}
}

image-20210930100746466

image-20210930100757523

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

image-20210930101046073

image-20210930101833536

红色的代表稳定

蓝色的代表不稳定

image-20210930101911329

策略模式

违背开闭原则

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 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); //多态调用 依赖于strategyFactory->NewStrategy()返回的是哪个子类对象
        //...
    }
    
};

image-20210930104008253

image-20210930104030608

image-20210930104159168

红色保持稳定,蓝色变化的部分

image-20210930104830324

观察者模式

image-20211005090859569

一、没有使用观察者模式

看代码

FileSplitter.cpp

class FileSplitter
{
	string m_filePath;
	int m_fileNumber;
	ProgressBar* m_progressBar;// 通知控件  这里如果我们不想要用进度条的形式来通知进度了,而是想用百分比的形势呈现呢? 岂不是不好改

public:
	FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :
		m_filePath(filePath), 
		m_fileNumber(fileNumber),
		m_progressBar(progressBar){

	}

	void split(){

		//1.读取大文件

		//2.分批次向小文件中写入
		for (int i = 0; i < m_fileNumber; i++){
			//...
			//分隔
			if (m_progressBar != nullptr)
			{
				float progressValue = m_fileNumber;
				progressValue = (i + 1) / progressValue;

				m_progressBar->setValue(progressValue);//更新进度条
			}
			
		}

	}
};

MainForm.cpp

class MainForm : public Form
{
	TextBox* txtFilePath;
	TextBox* txtFileNumber;
	ProgressBar* progressBar;

public:
	void Button1_Click(){

		string filePath = txtFilePath->getText();
		int number = atoi(txtFileNumber->getText().c_str());

		FileSplitter splitter(filePath, number, progressBar);

		splitter.split();

	}
};


二、使用了观察者设计模式

FileSplitter.cpp

class IProgress{
public:
	virtual void DoProgress(float value)=0;
	virtual ~IProgress(){}
};



class FileSplitter
{
	string m_filePath;
	int m_fileNumber;
	//ProgressBar* m_progressBar;// 通知控件 紧耦合
	List<IProgress*>  m_iprogressList; // 抽象通知机制,支持多个观察者(有了addIProgress和removeIProgress) 松耦合
	
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);//发送通知
		}

	}

	//加入IProgress
	void addIProgress(IProgress* iprogress){ 
		m_iprogressList.push_back(iprogress);
	}

	//删除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具体是什么类来选择
			itor++;
		}
	}
};

MainForm.cpp

//采用一对多的观察者模式  
//如果我们想用百分比的形式来做通知空间 我们可以再定义一个类 这个类来接受百分比的信息 然后在mainform类里面定义一个这个类的对象 然后add到m_iprogressList里面
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;
		CirclePercent cp;
		FileSplitter splitter(filePath, number);

		splitter.addIProgress(this); //订阅通知 
		splitter.addIProgress(&cn); //订阅通知
		splitter.addIProgress(&cp); //订阅通知
		splitter.split();

		splitter.removeIProgress(this);

	}

	virtual void DoProgress(float value){
		progressBar->setValue(value);
	}
};

class ConsoleNotifier : public IProgress {
public:
	virtual void DoProgress(float value){
		cout << ".";
	}
};

//这边是自己加入的显示百分比 假如界面windows已经有一个圆盘形式百分比的组件了
class CirclePercent:public IProgress {
	CirclePanelPercent* circlePanelPercent;

public:
	virtual void DoProgress(float value) {
		circlePanelPercent->setvalue(value);
	}
};





image-20211005093413980

image-20211005093612821

红色的部分是稳定的部分,依赖的部分。 蓝色的是改变的部分

image-20211005093909661

装饰模式

image-20211005100131413

image-20211005100116846

image-20211005100446792

image-20211005102228996

对于扩展操作来说 既可以加密 也可以缓冲 加入有m个扩展操作 那么总共组合就是 (m+m-1+ ….+1)/2 m>2 ,n代表文件流种类。

decorator1.cpp

//业务操作
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 CryptoFileStream :public FileStream{
public:
    virtual char Read(int number){
       
        //额外的加密操作...
        FileStream::Read(number);//读文件流
        
    }
    virtual void Seek(int position){
        //额外的加密操作...
        FileStream::Seek(position);//定位文件流
        //额外的加密操作...
    }
    virtual void Write(byte data){
        //额外的加密操作...
        FileStream::Write(data);//写文件流
        //额外的加密操作...
    }
};

class CryptoNetworkStream : :public NetworkStream{
public:
    virtual char Read(int number){
        
        //额外的加密操作... 这里重复了代码
        NetworkStream::Read(number);//读网络流
    }
    virtual void Seek(int position){
        //额外的加密操作... 这里重复了代码
        NetworkStream::Seek(position);//定位网络流
        //额外的加密操作...
    }
    virtual void Write(byte data){
        //额外的加密操作... 这里重复了代码
        NetworkStream::Write(data);//写网络流
        //额外的加密操作...
    }
};

class CryptoMemoryStream : public MemoryStream{
public:
    virtual char Read(int number){
        
        //额外的加密操作... 这里重复了代码
        MemoryStream::Read(number);//读内存流
    }
    virtual void Seek(int position){
        //额外的加密操作... 这里重复了代码
        MemoryStream::Seek(position);//定位内存流
        //额外的加密操作...
    }
    virtual void Write(byte data){
        //额外的加密操作... 这里重复了代码
        MemoryStream::Write(data);//写内存流
        //额外的加密操作...
    }
};

class BufferedFileStream : public FileStream{
    //...
};

class BufferedNetworkStream : public NetworkStream{
    //...
};

class BufferedMemoryStream : public MemoryStream{
    //...
}




class CryptoBufferedFileStream :public FileStream{
public:
    virtual char Read(int number){
        
        //额外的加密操作...
        //额外的缓冲操作...
        FileStream::Read(number);//读文件流
    }
    virtual void Seek(int position){
        //额外的加密操作...
        //额外的缓冲操作...
        FileStream::Seek(position);//定位文件流
        //额外的加密操作...
        //额外的缓冲操作...
    }
    virtual void Write(byte data){
        //额外的加密操作...
        //额外的缓冲操作...
        FileStream::Write(data);//写文件流
        //额外的加密操作...
        //额外的缓冲操作...
    }
};



void Process(){

        //编译时装配
    CryptoFileStream *fs1 = new CryptoFileStream();

    BufferedFileStream *fs2 = new BufferedFileStream();

    CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();

}

可以看到上面有很多冗余的代码

decorator2.cpp

利用多态消除冗余(组合的方式)

//业务操作
//利用多态消除冗余
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* stream;//...

public:
    CryptoStream(Stream* stm):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);//对文件流的加密和缓存
    
    

}

decorator3.cpp

进一步完善

//业务操作
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){
        //写内存流
    }
    
};

//扩展操作

DecoratorStream: public Stream{
protected:
    Stream* stream;//...
    
    DecoratorStream(Stream * stm):stream(stm){
    
    }
    
};

class CryptoStream: public DecoratorStream {
 

public:
    CryptoStream(Stream* stm):DecoratorStream(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 DecoratorStream{
    
    Stream* stream;//...
    
public:
    BufferedStream(Stream* stm):DecoratorStream(stm){
        
    }
    //...
};




void Process(){

    //运行时装配
    FileStream* s1=new FileStream();
    
    CryptoStream* s2=new CryptoStream(s1);
    
    BufferedStream* s3=new BufferedStream(s1);
    
    BufferedStream* s4=new BufferedStream(s2);
    
    

}

image-20211005102253916

image-20211005102355802

主体和扩展应该分开

image-20211005102636622

image-20211005102715926红色代表稳定的部分,蓝色代表变化的部分

image-20211005102940559

桥模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AbDL8kiv-1633576343142)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006093236260.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NHbbPKJz-1633576343142)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006093243637.png)]

bridge1.cpp

继承太多了,导致类数目太多,代码冗余

class Messager{
public:
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;

    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    
    virtual ~Messager(){}
};


//平台实现 n

class PCMessagerBase : public Messager{
public:
    
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};

class MobileMessagerBase : public Messager{
public:
    
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};



//业务抽象 m
//类的数目:1+n+m*n


class PCMessagerLite : public PCMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        PCMessagerBase::DrawShape();
        //........
    }
};



class PCMessagerPerfect : public PCMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::DrawShape();
        //........
    }
};


class MobileMessagerLite : public MobileMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        MobileMessagerBase::DrawShape();
        //........
    }
};


class MobileMessagerPerfect : public MobileMessagerBase {
public:
    
    virtual void Login(string username, string password){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::DrawShape();
        //........
    }
};


void Process(){
        //编译时装配
        Messager *m =
            new MobileMessagerPerfect();
}



bridge2.cpp

将平台与业务分离,采用组合的方法,减少类的数目,减少代码的冗余

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;

   
    
    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*n


class MessagerLite : public Messager {
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 {
public:
    
    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(){
        //运行时装配
        //编译的时候类ide数目1+n+m
        //运行时实现的功能数目和之前没有使用桥模式一样
        //比如想要对pc平台操作
            MessagerImp* imp = new PCMessagerImp();
            Messager *m= new Messager(imp);//调用构造 说明m这个类里面的messagerImp指针指向PCMessagerImp子类 
                                            //因此下面的MessagerLite和MessagerPerfect调用的都是PC平台下的方法
            m->Login();
            m->SendMessage();
            m->SendPicture();
}



[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmjeATc6-1633576343143)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006094403801.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ovX5GFUu-1633576343143)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006094705463.png)]

红色稳定,蓝色不稳定.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sb2q47Am-1633576343143)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006094611645.png)]

工厂方法模式

没有使用工厂设计模式

MainForm.cpp

class MainForm : public Form
{
	TextBox* txtFilePath;
	TextBox* txtFileNumber;
	ProgressBar* progressBar;

public:
	void Button1_Click(){


        
		ISplitter * splitter=
            new BinarySplitter();//依赖具体类
        
        splitter->split();

	}
};

FileSplitter.cpp

class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};

class BinarySplitter : public ISplitter{
    
};

class TxtSplitter: public ISplitter{
    
};

class PictureSplitter: public ISplitter{
    
};

class VideoSplitter: public ISplitter{
    
};


我们如何让才能让mainform不依赖具体类那呢?采用工厂设计模式

使用工厂设计模式

MainForm.cpp

class MainForm : public Form
{
    SplitterFactory*  factory;//工厂

public:
    
    MainForm(SplitterFactory*  factory){//创建什么类型的工厂在这里面执行 
        this->factory=factory;
    }
    
	void Button1_Click(){

        
		ISplitter * splitter=
            factory->CreateSplitter(); //多态new
        
        splitter->split();

	}
};

//怎么使用呢
int main()
{
    SplitterFactory* f = new BinarySplitterFactory();//以这个为例子
    MainForm *m=new MainForm(f) ;
    m->Button1_Click();

    return 0;
}




ISplitterFactory.cpp


//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};


//工厂基类
class SplitterFactory{
public:
    virtual ISplitter* CreateSplitter()=0;
    virtual ~SplitterFactory(){}
};




FileSplitter.cpp



//具体类
class BinarySplitter : public ISplitter{
    
};

class TxtSplitter: public ISplitter{
    
};

class PictureSplitter: public ISplitter{
    
};

class VideoSplitter: public ISplitter{
    
};

//具体工厂
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();
    }
};


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiiUNNTZ-1633576343144)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006102203491.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vPtNO1fC-1633576343144)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006102329732.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZwpcac9-1633576343144)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006102345658.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bFRrRqb6-1633576343144)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006102320723.png)]

红色稳定,蓝色不稳定,mainform继承红色。

目的就是把红色和蓝色分离

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQciI8Hr-1633576343145)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211006102509272.png)]

抽象工厂

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ShZFyAH6-1633576343145)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007100650458.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSGxpGqJ-1633576343145)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007100918369.png)]

下面三段代码都是关于不同数据库访问的代码

EmployeeDAO1.cpp


class EmployeeDAO{
//对数据库的访问 这个类不能访问不同类型的数据库    
public:
    vector<EmployeeDO> GetEmployees(){
        SqlConnection* connection =
            new SqlConnection();
        connection->ConnectionString = "...";

        SqlCommand* command =
            new SqlCommand();
        command->CommandText="...";
        command->SetConnection(connection);

        SqlDataReader* reader = command->ExecuteReader();
        while (reader->Read()){

        }

    }
};

EmployeeDAO2.cpp

采用工厂模式


//数据库访问有关的基类
class IDBConnection{
    
};
class IDBConnectionFactory{
public:
    virtual IDBConnection* CreateDBConnection()=0;
};

//数据库访问有关的基类
class IDBCommand{
    
};
class IDBCommandFactory{
public:
    virtual IDBCommand* CreateDBCommand()=0;
};

//数据库访问有关的基类
class IDataReader{
    
};
class IDataReaderFactory{
public:
    virtual IDataReader* CreateDataReader()=0;
};

//支持SQL Server
class SqlConnection: public IDBConnection{
    
};
class SqlConnectionFactory:public IDBConnectionFactory{
    
};

class SqlCommand: public IDBCommand{
    
};
class SqlCommandFactory:public IDBCommandFactory{
    
};

class SqlDataReader: public IDataReader{
    
};
class SqlDataReaderFactory:public IDataReaderFactory{
    
};

//支持Oracle
class OracleConnection: public OracleConnection{
    
};
class OracleConnectionFactory:public OracleConnectionFactory{
    
};
class OracleCommand: public IDBCommand{
    
};
class OracleCommandFactory:public OracleCommandFactory{
    
};
class OracleDataReader: public IDataReader{
    
};
class OracleDataReaderFactory:public OracleDataReaderFactory{
    
};

class EmployeeDAO
{
    IDBConnectionFactory* dbConnectionFactory;
    IDBCommandFactory* dbCommandFactory;
    IDataReaderFactory* dataReaderFactory;
    public:
    vector<EmployeeDO> GetEmployees()
    {
        IDBConnection* connection=dbConnectionFactory->CreateDBConnection();//dbConnectionFactory在构造函数里赋值
        connection->ConnectionString("...");

        IDBCommand* command =
            dbCommandFactory->CreateDBCommand();
        command->CommandText("...");
        command->SetConnection(connection); //关联性
        IDBDataReader* reader = command->ExecuteReader(); //关联性
        while (reader->Read()){

        }
        
    }
}

从上面的代码可以看出这里的工厂模式针对每种不同的数据库,都弄了一个工厂

EmployeeDAO3.cpp

可以看到上面代码同种类型的数据库的连接 命令读取都是相关联的,那么我们就把 IDBConnection IDBCommand IDataReader的创建放在一个类里面


//数据库访问有关的基类
class IDBConnection{
    
};

class IDBCommand{
    
};

class IDataReader{
    
};


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{
    
};


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 OracleDBFactory:public IDBFactory{
public:
    virtual IDBConnection* CreateDBConnection()=0;
    virtual IDBCommand* CreateDBCommand()=0;
    virtual IDataReader* CreateDataReader()=0;
 
};

class EmployeeDAO{
    IDBFactory* dbFactory;
    
public:
    vector<EmployeeDO> GetEmployees(){
        IDBConnection* connection =
            dbFactory->CreateDBConnection();//dbFactory在构造函数里面赋值
        connection->ConnectionString("...");

        IDBCommand* command =
            dbFactory->CreateDBCommand();
        command->CommandText("...");
        command->SetConnection(connection); //关联性

        IDBDataReader* reader = command->ExecuteReader(); //关联性
        while (reader->Read()){

        }

    }
};

可以看出抽象模式和工厂模式很类似,工厂模式就有点像是特殊的抽象模式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hlYGoqjA-1633576343146)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007102113334.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k0aFims5-1633576343146)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007102253229.png)]

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

AbstractFactory相当于是IDBFactory

AbstractProductA相当于是IDBConnection

AbstractProductB相当于是IDBCommand

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K4xdBpE5-1633576343146)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007102457687.png)]

原型模式Prototype

image-20211007104819956

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bjAQGR8D-1633576343147)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20211007104757919.png)]

client.cpp

class MainForm : public Form
{
    ISplitter*  prototype;//原型对象

public:
    
    MainForm(ISplitter*  prototype){
        this->prototype=prototype;
    }
    
	void Button1_Click(){

		ISplitter * splitter=
            prototype->clone(); //克隆原型
        
        splitter->split();
        
        

	}
};

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(){
        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);//深拷贝构造自己 实现克隆自己
    }
};

可以和工厂模式那一章节做对比,如果说实现的类里面有些中间状态很复杂,你又想保留,建议用原型模式 ,也就是拷贝。

image-20211007105540830

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

红色是稳定部分 抽象类 ISplitter

蓝色是变化部分,也就是具体类 BinarySplitter TxtSplitter等

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ednlttq-1633576343148)(https://i.loli.net/2021/10/07/9GJbu7Bgkhz8nP1.png)]
onString("…");

    IDBCommand* command =
        dbFactory->CreateDBCommand();
    command->CommandText("...");
    command->SetConnection(connection); //关联性

    IDBDataReader* reader = command->ExecuteReader(); //关联性
    while (reader->Read()){

    }

}

};




可以看出抽象模式和工厂模式很类似,工厂模式就有点像是特殊的抽象模式。

[外链图片转存中...(img-hlYGoqjA-1633576343146)]

[外链图片转存中...(img-k0aFims5-1633576343146)]

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

AbstractFactory相当于是IDBFactory 

AbstractProductA相当于是IDBConnection

AbstractProductB相当于是IDBCommand

[外链图片转存中...(img-K4xdBpE5-1633576343146)]

# 原型模式Prototype

[外链图片转存中...(img-eJZFlSG6-1633576343147)]

[外链图片转存中...(img-bjAQGR8D-1633576343147)]

client.cpp

~~~c++
class MainForm : public Form
{
    ISplitter*  prototype;//原型对象

public:
    
    MainForm(ISplitter*  prototype){
        this->prototype=prototype;
    }
    
	void Button1_Click(){

		ISplitter * splitter=
            prototype->clone(); //克隆原型
        
        splitter->split();
        
        

	}
};

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(){
        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);//深拷贝构造自己 实现克隆自己
    }
};

可以和工厂模式那一章节做对比,如果说实现的类里面有些中间状态很复杂,你又想保留,建议用原型模式 ,也就是拷贝。

[外链图片转存中…(img-TFqnVQHA-1633576343147)]

[外链图片转存中…(img-OqUn3kXF-1633576343148)]

红色是稳定部分 抽象类 ISplitter

蓝色是变化部分,也就是具体类 BinarySplitter TxtSplitter等

[外链图片转存中…(img-3Ednlttq-1633576343148)]

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值