创建型模式学习完了,接下来学习的是结构性模式。结构型模式主要涉及到如何组合类和对象以获得更大的结构,通常采用继承机制来组合接口和实现。
首先学习的是适配器模式。首先是适配器的定义:
适配器模式,将一个类的接口转换成客户所希望的另外一个接口。适配器模式使得原来由于接口不兼容而不能一起工作的类可以一起工作。
简单的说当系统的数据和行为都正确时,但接口不符时,我们应该考虑使用适配器模式。目的是是控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望用一些现存的类,但是接口又与复用环境要求不一致的情况。俗话说的好,智者千虑,必有一失。类的编写者可能考虑不到后期软件需求的变化。此时,适配器模式就派上用场了。根据GOF的设计模式,分为两种类的设计模式和对象适配器模式。
类适配器模式的结构图:
对象适配器模式结构图:
适用性
1 你想使用一个已经存在的类,而他的接口不符合你的要求
2 你想创建一个可以复用的类,该类可以与其他不相关的或不可预见的类协同工作
3 你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口。对象适配器可以适配它的父类接口。(仅适用于对象适配器)
协作
Client在Adapter实例上调用一些操作。接着适配器调用Adaptee的操作实现这个请求。
类适配与对象适配的区别
类适配:
1 用一个具体的Adapter类对Adapter和Target进行匹配。结果是当我们想要匹配一个类以及所有子类时,类Adapter将不能胜任工作。
2 使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类
3 仅仅引入一个对象,并不需要额外的指针以间接得到adaptee
4 使用多重继承对一个接口与另一个接口进行匹配
对象适配:
1 允许一个Adapter与多个adaptee
2 使得重定义adaptee的行为比较困难
3 依赖于对象组合
需要考虑的其他因素
1 Adapter的匹配程度
2 可插入的adapter
3 使用双向适配器提供透明操作
例子,为了通用性因为很多语言并不支持多重继承,这里暂时先给出对象适配器的例子
// Adapter.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Translate.h"
#include "BikePlayer.h"
int _tmain(int argc, _TCHAR* argv[])
{
BikePlayer* bikePlayer = new BikePlayer;
Translate* translate = new Translate(bikePlayer);
translate->say();
return 0;
}
#pragma once
class Player
{
public:
Player();
~Player();
virtual void say() = 0;
private:
};
#pragma once
#include "Player.h"
class BasketBallPlayer : public Player
{
public:
BasketBallPlayer();
~BasketBallPlayer();
virtual void say();
private:
};
#include "BasketBallPlayer.h"
#include <iostream>
using namespace std;
BasketBallPlayer::BasketBallPlayer()
{
}
BasketBallPlayer::~BasketBallPlayer()
{
}
void BasketBallPlayer::say()
{
cout << "篮球运动员" << endl;
}
#pragma once
#include "Player.h"
class FootBallPlayer : public Player
{
public:
FootBallPlayer();
~FootBallPlayer();
virtual void say();
private:
};
#include "FootBallPlayer.h"
#include <iostream>
using namespace std;
FootBallPlayer::FootBallPlayer()
{
}
FootBallPlayer::~FootBallPlayer()
{
}
void FootBallPlayer::say()
{
cout << "足球运动员" << endl;
}
#pragma once
#include "Player.h"
#include "BikePlayer.h"
class Translate : public Player
{
public:
Translate(BikePlayer* bikePlayer);
~Translate();
virtual void say();
private:
BikePlayer* m_bikePlayer;
};
#include "Translate.h"
Translate::Translate(BikePlayer* bikePlayer)
:m_bikePlayer(bikePlayer)
{
}
Translate::~Translate()
{
}
void Translate::say()
{
m_bikePlayer->bsay();
}
#pragma once
class BikePlayer
{
public:
BikePlayer();
~BikePlayer();
void bsay();
private:
};
#include "BikePlayer.h"
#include <iostream>
using namespace std;
BikePlayer::BikePlayer()
{
}
BikePlayer::~BikePlayer()
{
}
void BikePlayer::bsay()
{
cout << "自行车运动员" << endl;
}