结构图:
结构型模式涉及到如何组合类和对象以获得更大的结构。
结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而
实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有
更大的灵活性,而这种机制用静态类组合是不可能实现的。
定义:Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本
由于接口不兼容而不能一起工作的那些类可以一起工作。
尽管Adapter模式的实现方式通常简单直接,但是仍需要注意以下一些问题:
在使用C++实现适配器类时,Adapter类应该采用公共方式继承Target类,并且用私有方式
继承Adaptee类。因此,Adapter类应该是Target的子类型,但不是Adaptee的子类型。
适配器模式有两种方法实现,一种是类适配器,一种是对象适配器。
类适配器和对象适配器有不同的权衡。类适配器
1、用一个具体的Adapter类对Adaptee和Target进行匹配。结果是当我们想要匹配生个类以
及所有它的子类时,类Adapter将不能胜任工作。
2、使得Adapter可以重定义Adapter的部分行为,因为Adapter是Adaptee的一个子类。
3、仅仅引入了一个对象,并不需要额外的指针以间接得到adaptee.
对象适配器则
1、允许一个Adapter与多个Adaptee,即Adaptee本身以及它的所有子类(如果有子类的话)
同时工作。Adapter也可以一次给所有的Adaptee添加功能。
2、使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且使得Adapter引用
这个子类而不是引用adaptee本身。
本章用两个实例分别讲述类适配器模式和对象适配器模式。
对于结构型模式,由于需要用到一些结构,因此这里先贴出来,部分只有申明无实现是因为还未被用到,用到时会逐步补上去的。
一、类适配器
//
/**///////////////////////////////////////////////////////////////////////
#if !defined(AFX_BASICCLASS_H__459C19CB_0047_4A50_855E_B7FDCFC6F3B0__INCLUDED_)
#define AFX_BASICCLASS_H__459C19CB_0047_4A50_855E_B7FDCFC6F3B0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//
// #include <iostream>
// using namespace std;
#include <iostream.h>
#define DEFAULT_LIST_CAPACITY 1000
template<class Item> class List
...{
public:
List(long size = DEFAULT_LIST_CAPACITY);
List(List&);
~List();
List& operator=(const List&);
long Count() const;
Item& Get(long index) const;
Item& First() const;
Item& Last() const;
bool Includes(const Item&) const;
void Append(const Item&);
void Prepend(const Item&);
void Remove(const Item&);
void RemoveLast();
void RemoveFirst();
void RemoveAll();
Item& Top() const;
void Push(const Item&);
Item& Pop();
};
template<class Item> class iterator
...{
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
virtual Item CurrentItem() const = 0;
protected:
iterator();
};
template<class Item> class ListIterator: public iterator<Item>
...{
public:
ListIterator(const List<Item>* aList);
virtual void First();
virtual void Next();
virtual bool IsDone();
virtual Item CurrentItem() const;
};
//CPoint
typedef float Coord;
class Point...{
public:
static const Point Zero;
Point(Coord x = 0.0,Coord y = 0.0);
Coord X() const;//得到x值
Coord Y() const;
void X(Coord x);//设置x值
void Y(Coord y);
Point operator+(const Point&);
Point operator-(const Point&);
Point operator*(const Point&);
Point operator/(const Point&);
void operator+=(const Point&);
void operator-=(const Point&);
void operator*=(const Point&);
void operator/=(const Point&);
bool operator==(const Point&);
bool operator!=(const Point&);
friend ostream& operator<<(ostream&, const Point&);
friend istream& operator>>(istream&, Point&);
private:
Coord m_x;
Coord m_y;
};
class Rect
...{
public:
static const Rect Zero;
Rect(Coord x, Coord y, Coord w, Coord h);
Rect(const Point& origin, const Point& extent);
Coord Width() const;
void Width(Coord);
Coord Height() const;
void Height(Coord);
Coord Left() const;
void Left(Coord);
Coord Bottom() const;
void Bottom(Coord);
Point& Origin() const;
void Origin(const Point&);
Point& Extent() const;
void Extent(const Point&);
void MoveTo(const Point&);
void MoveBy(const Point&);
bool IsEmpty() const;
bool Contains(const Point&) const;
};
#endif // !defined(AFX_BASICCLASS_H__459C19CB_0047_4A50_855E_B7FDCFC6F3B0__INCLUDED_)
// BasicClass.cpp: implementation of the BasicClass class.
//
/**///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BasicClass.h"
Point::Point(Coord x /**//* = 0.0 */,Coord y /**//* = 0.0 */)
...{
m_x = x;
m_y = y;
}
Coord Point::X() const
...{
return m_x;
}
Coord Point::Y() const
...{
return m_y;
}
void Point::X(Coord x)
...{
m_x = x;
}
void Point::Y(Coord y)
...{
m_y = y;
}
Point Point::operator +(const Point& p)
...{
return Point(m_x+p.m_x, m_y + p.m_y);
}
Point Point::operator -(const Point& p)
...{
return Point(m_x-p.m_x, m_y-p.m_y);
}
Point Point::operator *(const Point& p)
...{
return Point(m_x* p.m_x, m_y* p.m_y);
}
Point Point::operator /(const Point& p)
...{
return Point(m_x/p.m_x, m_y/p.m_y);
}
void Point::operator +=(const Point& p)
...{
m_x += p.m_x;
m_y += p.m_y;
}
//CPoint
void Point::operator -=(const Point& p)
...{
m_x -= p.m_x;
m_y -= p.m_y;
}
void Point::operator *=(const Point& p)
...{
m_x *= p.m_x;
m_y *= p.m_y;
}
void Point::operator /=(const Point& p)
...{
m_x /= p.m_x;
m_y /= p.m_y;
}
bool Point::operator==(const Point& p)
...{
return (m_x == p.m_x && m_y == p.m_y);
}
bool Point::operator!=(const Point& p)
...{
return !(*this== p);
}
ostream& operator<<(ostream& cout,const Point& p)
...{
cout<<p.m_x<<","<<p.m_y;
return cout;
}
istream& operator>>(istream& in, Point& p)
...{
in>>p.m_x>>p.m_y;
return in;
}
类适配器模式例,在这里,TextView认为是一个工具箱,没有源码,为了调用其中的功能,需要用一个类TextShape来调用TextView中的功能,这里TextShape就叫做适配器类,它的接口BoundingBox()调用TextView中的GetExtent(),实现通过一致的接口,完成GetExtent()功能的要求。CreateManipulator功能在原TextView中没有,这是对于原有TextView中功能增强的一种方式。
代码如下:
//
/**///////////////////////////////////////////////////////////////////////
#if !defined(AFX_ADAPTER_H__02F2DD6D_CFF8_4E63_A14B_63C2E58ACB53__INCLUDED_)
#define AFX_ADAPTER_H__02F2DD6D_CFF8_4E63_A14B_63C2E58ACB53__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "BasicClass.h"
class Manipulator;
class Shape;
class TextManipulator;
class TextShape;
class TextView;
class Manipulator
...{
public:
Manipulator()...{}
};
class TextManipulator: public Manipulator
...{
public:
TextManipulator(const Shape* sp)...{ m_pShape = (Shape*)sp; }
private:
Shape* m_pShape;
};
class Shape...{
public:
Shape()...{}
virtual void BoundingBox(Point& bottomLeft,Point& topRight) const
...{
bottomLeft = m_bottomLeft;
topRight = m_topRight;
}
virtual Manipulator* CreateManipulator() const
...{
return new Manipulator();
}
private:
Point m_bottomLeft;
Point m_topRight;
};
class TextView
...{
public:
TextView(Point org =0, Coord width = 0, Coord height = 0);
void GetOrigin(Coord& x, Coord& y) const;
void GetExtent(Coord& width, Coord& height) const;
virtual bool IsEmpty() const;
private:
Point m_org;//原点
Coord m_width;//宽度
Coord m_height;//高度
};
class TextShape: public Shape, private TextView
...{
public:
TextShape()...{}
virtual void BoundingBox(Point& bottomLeft,Point& topRight) const;
virtual bool IsEmpty() const;
virtual Manipulator* CreateManipulator() const;
};
#endif // !defined(AFX_ADAPTER_H__02F2DD6D_CFF8_4E63_A14B_63C2E58ACB53__INCLUDED_)
// Adapter.cpp: implementation of the Adapter class.
//
/**///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Adapter.h"
/**///////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
TextView::TextView(Point org /**//* =0 */, Coord width /**//* = 0 */, Coord height /**//* = 0 */)
...{
m_org = org;
m_width = width;
m_height = height;
}
void TextView::GetOrigin(Coord& x, Coord& y) const
...{
x = m_org.X();
y = m_org.Y();
}
void TextView::GetExtent(Coord& width, Coord& height) const
...{
width = m_width;
height = m_height;
printf("TextView::GetExtent() ");
}
bool TextView::IsEmpty() const
...{
return (m_width>0 && m_height>0);
}
/**///////////////////////////////////////////////////////////////////////////
//通过BoundingBox调用TextShape()中的接口,达到适配的目的
void TextShape::BoundingBox(Point& bottomLeft,Point& topRight) const
...{
Coord bottom, left, width, height;
GetOrigin(bottom, left);
GetExtent(width, height);
bottomLeft = Point(bottom, left);
topRight = Point(bottom + height, left + width);
}
bool TextShape::IsEmpty() const
...{
return TextView::IsEmpty();
}
Manipulator* TextShape::CreateManipulator() const
...{
return new TextManipulator(this);
}
// testConfig.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "BasicClass.h"
#include "Adapter.h"
int main(int argc, char* argv[])
...{
printf("Hello World! ");
TextShape ts;
Point p1(1,2);
Point p2(3,4);
ts.BoundingBox(p1,p2);
return 0;
}
二、对象适配器
对象适配器的功用和类适配器相同,不过它不是采用多重继承来实现,而是通过组合的方式,在适配器类中定义一个被适配的子对象(Adaptee),通过这个子对象完成适配的功能。
相关代码和前面代码类似,只需改动以下部分即可。
class TextShape: public Shape
...{
public:
TextShape(TextView* t)...{ _text = t; }
virtual void BoundingBox(Point& bottomLeft,Point& topRight) const;
virtual bool IsEmpty() const;
virtual Manipulator* CreateManipulator() const;
private:
TextView * _text;
};
//通过BoundingBox调用TextShape()中的接口,达到适配的目的
void TextShape::BoundingBox(Point& bottomLeft,Point& topRight) const
...{
Coord bottom, left, width, height;
_text->GetOrigin(bottom, left);
_text->GetExtent(width, height);
bottomLeft = Point(bottom, left);
topRight = Point(bottom + height, left + width);
}
bool TextShape::IsEmpty() const
...{
return _text->IsEmpty();
}
Manipulator* TextShape::CreateManipulator() const
...{
return new TextManipulator(this);
}
int main(int argc, char* argv[])
...{
printf("Hello World! ");
TextView tv;
TextShape ts(&tv);
Point p1(1,2);
Point p2(3,4);
ts.BoundingBox(p1,p2);
return 0;
}