设计模式——适配器模式

结构性模式:处理多个类组合的关系。

动机:一些现存在的对象放在新环境中,新环境要求的 接口是这个现存的对象不满足的。

定义:适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。它包括类适配器和对象适配器。


对象适配器:

#include<iostream>
#include <list>

using namespace std;

//这个是需要适配的类,这个类已经非常稳定。 
class Deque  
{  
public:  
	void push_back(int x) { cout<<"Deque push_back"<<endl; }  
	void push_front(int x) { cout<<"Deque push_front"<<endl; }  
	void pop_back() { cout<<"Deque pop_back"<<endl; }  
	void pop_front() { cout<<"Deque pop_front"<<endl; }  
}; 


//这个是客户希望的接口,只有push和pop两个方法,但是Deque没有这两个方法。
class Sequence  
{  
public:  
	virtual void push(int x) = 0;  
	virtual void pop() = 0;  
}; 

//这个是第一个适配器。实现了栈
class Stack: public Sequence  
{  
public:  
	void push(int x) { deque.push_back(x); }  
	void pop() { deque.pop_back(); }  
private:  
	Deque deque; //双端队列  
};

//这是第二个适配器,实现了队列  
class Queue: public Sequence  
{  
public:  
	void push(int x) { deque.push_back(x); }  
	void pop() { deque.pop_front(); }  
private:  
	Deque deque; //双端队列  
}; 
#include "Test.h"

int main()  
{  
	Sequence *s1 = new Stack();  
	Sequence *s2 = new Queue();  
	s1->push(1); //调用适配器的接口,接口转换工作由适配器去完成。
	s1->pop();  
	s2->push(1); 
	s2->pop();  
	delete s1; delete s2;  
	return 0;  
}


类适配器

例子2:

#include<iostream>
#include <vector>

using namespace std;

class CShape  //一个绘图模型
{
public:
	~CShape() {};

	virtual void Draw() = 0;
};

class CRectangle : public CShape  //可以绘长方形
{
public:
	void Draw() { cout << "Draw a rectangle." << endl; };
};


class CSquare : public CShape  //可以绘正方形。
{
public:
	void Draw() { cout << "Draw a square." << endl; };
};

class CView : public CShape
{
public:
	~CView()
	{
		while(!m_vShape.empty())
		{
			CShape *pShape = (CShape*)m_vShape.back();
			m_vShape.pop_back();
			delete pShape;
		}
	}

	void Draw()
	{
		cout << "Draw a view." << endl;

		for (vector<CShape*>::const_iterator it = m_vShape.begin(); it != m_vShape.end(); ++it)
		{
			(*it)->Draw();
		}
			
	}

	void AddShape(CShape *pShape)
	{
		if (pShape)
		{
			m_vShape.push_back(pShape);
		}		
	}

private:
	vector<CShape*> m_vShape;
};
#include "Test.h"

int main()  
{  
	CView view;

	CRectangle *pRectangle = new CRectangle;
	view.AddShape(pRectangle);

	CSquare *pSquare = new CSquare;
	view.AddShape(pSquare);

	view.Draw(); 
	return 0;  
}

变化:现在需要绘制文本类,有一个现存的类,但是没有对应的接口。

class CContext  //绘制文本基类
{
public:
    ~CContext() {};

    virtual void DrawText() = 0;  //这个类与上面的绘图类接口不一致。
};

// 这里也以输出一句话来代替具体的draw过程

class CText : public CContext
{
public:
    void DrawText() { cout << "Draw a text." << endl; };
};


由于类CText 的父类不是CShape,而且接口跟我们想要的接口不一样。为了在我们的系统中使用类CText 来显示文本,就可以使用适配器模式创建一个类CText 的adapter,使CText 的接口适应我们已经写好的视图系统。

用类适配器实现。

class CShapeText : public CShape, private CText
{
public:
	void Draw() { DrawText(); };  //这里实现Cshape的接口

private:
	void DrawText()             //这里实现CTest的接口
	{
		CText::DrawText();

		// 这里可以改变父类的部分行为。而不是简单的直接调用。
		cout << "  It is a text adapter." << endl;
	}
};

具体的使用:

int main()  
{  
	CView view;

	CRectangle *pRectangle = new CRectangle;
	view.AddShape(pRectangle);

	CSquare *pSquare = new CSquare;
	view.AddShape(pSquare);

	// 在这里CShapeText跟其他CShape的子类一样的使用
	// 完全融入到已开发好的视图系统中
	CShapeText *pText = new CShapeText;
	view.AddShape(pText);

	view.Draw(); 
	return 0;  
}

用对象适配的实现方式:

class CShapeText : public CShape
{
public:
    CShapeText(CContext *pText) { m_pText = pText; };

    void Draw() { m_pText->DrawText(); };  //这里去调用类的方法

private:
    CContext *m_pText;
};

具体的使用方式:

int main()  
{  
	CView view;

	CRectangle *pRectangle = new CRectangle;
	view.AddShape(pRectangle);

	CSquare *pSquare = new CSquare;
	view.AddShape(pSquare);

	// 这里的CShapeText一样可以很好的融入到已开发好的视图系统中
	CText *pText = new CText;
	CShapeText *pShapeText = new CShapeText(pText);
	view.AddShape(pShapeText);

	view.Draw(); 
	return 0;  
}

 类适配器:
    优点:可以重新定义被适配的类的部分行为。
    缺点:不能适配一个类以及它的子类。(暂时无法理解)
    对象适配器:
    优点:可以适配一个类以及它的所有子类。
    缺点:重新定义被适配的类的行为比较困难。
    因此,我们可以得出结论:如果要适配一个类以及它的子类,或者只是简单的包装以转换接口,那就使用对象适配器;其他情况就用类适配器。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值