17.1 在NBA我需要翻译
向姚明这样的在国外打球的运动员来说,如果不懂外语,球技再高,估计也是不可能在国外待很长时间的。这个就可以和适配器模式挂上钩了。
17.2 适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。简单来说,就是需要的东西就在面前,但却不能使用,而短时间又无法改造它,于是我们就想办法适配他。
在软件开发中,系统地数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。在适配器模式中有两个类型,类适配器和对象适配器模式。这里我们主要学习的是对象适配器模式。
Target.h
#pragma once #include <iostream> class Target { public: virtual void Request(void) { std::cout << "晛捠偺惪媮" << std::endl; }; }; class Adaptee { public: void SpecificRequest(void) { std::cout << "摿暿側惪媮" << std::endl; }; }; class Apapter : public Target { public: void Request(void) { m_pAdaptee->SpecificRequest(); }; private: Adaptee* m_pAdaptee; };
main函数
#include "stdafx.h" #include "Target.h" int _tmain(int argc, _TCHAR* argv[]) { Target* tag = new Apapter(); tag->Request(); return 0; }
17.3 何时使用适配器模式
两个类所做的事情相同或者相似,但是具有不同的接口的时候就可以使用适配器模式。而且由于类都共享同一个接口,使得客户端代码可以统一调用同一接口,这样应该可以更简单,更直接,更紧凑。当然最好在双方都不太容易修改的时候再使用适配器模式适配。当接口不相同的时候首先不应该考虑用适配器,而是应该考虑通过重构统一接口。
17.4 篮球翻译适配器
后卫,中锋,前锋都是球员,所以应该有一个球员抽象类,有进攻和防守的方法。但是姚明刚入NBA,所以还不懂进攻和防守方法的时候,就用到了适配器。
Player.h
#pragma once #include <string> #include <iostream> class Player { public: Player(std::string name) { m_Name = name; }; //峌寕 virtual void Attack() = 0; //杊塹 virtual void Defense() = 0; protected: std::string m_Name; }; //慜塹 class Forwards :public Player { public: Forwards(std::string name) :Player(name) { }; //峌寕 void Attack() { std::cout << "慜塹" << m_Name << "偺峌寕" << std::endl; }; //杊塹 void Defense() { std::cout << "慜塹" << m_Name << "偺杊塹" << std::endl; }; }; //拞塹 class Center :public Player { public: Center(std::string name) :Player(name) { }; //峌寕 void Attack() { std::cout << "拞塹" << m_Name << "偺峌寕" << std::endl; }; //杊塹 void Defense() { std::cout << "拞塹" << m_Name << "偺杊塹" << std::endl; }; }; //屻塹 class Guards :public Player { public: Guards(std::string name) :Player(name) { }; //峌寕 void Attack() { std::cout << "屻塹" << m_Name << "偺峌寕" << std::endl; }; //杊塹 void Defense() { std::cout << "屻塹" << m_Name << "偺杊塹" << std::endl; }; }; //奜崙偐傜棃偨拞塹 class ForeignCenter { public: //峌寕 void Attack() { std::cout << "奜崙偐傜棃偨拞塹" << m_Name << "偺峌寕" << std::endl; }; //杊塹 void Defense() { std::cout << "奜崙偐傜棃偨拞塹" << m_Name << "偺杊塹" << std::endl; }; void SetForeignName(std::string name) { m_Name = name; }; std::string GetForeignName(void) { return m_Name; }; private: std::string m_Name; }; //捠栿幰 class Translator : public Player { public: Translator(std::string name) :Player(name) { m_pForeignCenter = new ForeignCenter(); m_pForeignCenter->SetForeignName(name); }; ~Translator() { if (!m_pForeignCenter) { delete m_pForeignCenter; m_pForeignCenter = NULL; } }; //峌寕 void Attack() { m_pForeignCenter->Attack(); }; //杊塹 void Defense() { m_pForeignCenter->Defense(); }; private: ForeignCenter* m_pForeignCenter; };
Main函数
#include "stdafx.h" #include "Player.h" int _tmain(int argc, _TCHAR* argv[]) { Player* b = new Forwards("Shane Battier"); b->Attack(); Player* m = new Guards("McGrady"); m->Attack(); Player* yaoming = new Translator("yaoming"); yaoming->Attack(); yaoming->Defense(); return 0; }
17.5 适配器模式的.NET应用
DataAdapter用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射Fill中的数据以便与数据源中的数据相匹配。
17.6 扁鹊的医术
扁鹊家三兄弟,长兄最好,治人于病情发作之前;中兄次之,治人于病情发作前期,扁鹊为末,治人于病情发作到相当严重的时候。其实如果预先预防接口不同的问题,不匹配问题就不会发生,在有小的接口不统一时,即使重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配