概述
- 由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但新环境要求的接口是这些现存对象所不满足的
- 如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?
- Adapter举例
- 将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作
- 继承:遵循你定义的接口规范(is-a)
- 组合:支持一个实现(has-a)
- Adapter继承Target,并通过指针指向Adaptee(组合),实现了从Adaptee到Target的转换
- 继承新接口,组合老接口
- 代码仅示意,实际转换方式可能很复杂
- 希望复用一些现存的类,但接口又与复用环境要求不一致的情况,在遗留代码复用、类库迁移等方面非常有用
- GOF 23 定义了两种Adapter模式:对象适配器(采用组合方案)、类适配器(采用多继承模式,不推荐使用,多继承和组合在内存模型上接近)
- public继承:公有接口,符合你的接口规范
- private、protected继承:实现继承,没继承接口但用你的实现(has-a)
- 类的成员(函数、变量)在内存层面是一种东西
- 私有继承的用法:父类的public和protected成员在子类中变成了子类的private成员
- 意味着从父类继承过来的这些成员(public/protected),子类的成员函数可以调用之,但子类的对象就不能调用之(派生类成员只能访问基类中public/protected成员,派生类对象不能访问基类中的任何成员)
- 即在子类中可以调用父类的接口(public/protected),但这些接口不会暴露出去,实现了包含(composite)的特性
- 相比类适配器,对象适配器灵活性更高(指针可以指向不同对象)
示例
Adapter.cpp
1 //目标接口(新接口) 2 class ITarget{ 3 public: 4 virtual void process()=0; 5 }; 6 7 //遗留接口(老接口) 8 class IAdaptee{ 9 public: 10 virtual void foo(int data)=0; 11 virtual int bar()=0; 12 }; 13 14 //遗留类型 15 class OldClass: public IAdaptee{ 16 //.... 17 }; 18 19 //对象适配器 20 class Adapter: public ITarget{ //继承 21 protected: 22 IAdaptee* pAdaptee;//组合 23 24 public: 25 26 Adapter(IAdaptee* pAdaptee){ 27 this->pAdaptee=pAdaptee; 28 } 29 30 virtual void process(){ 31 int data=pAdaptee->bar(); 32 pAdaptee->foo(data); 33 34 } 35 }; 36 37 //类适配器 38 class Adapter: public ITarget, 39 protected OldClass{ //多继承 40 41 42 } 43 44 int main(){ 45 IAdaptee* pAdaptee=new OldClass(); 46 47 48 ITarget* pTarget=new Adapter(pAdaptee); 49 pTarget->process(); 50 51 52 } 53 54 class stack{ 55 deqeue container; 56 57 }; 58 59 class queue{ 60 deqeue container; 61 62 };View Code
参考
UML图
https://www.cnblogs.com/jiangds/p/6596595.html
protected成员
http://c.biancheng.net/view/252.html
私有成员:只能在类内使用
保护成员:类内,继承类内可以使用
共有成员:所有地方都可使用
私有继承:父类成员继承后变为子类私有成员
保护继承:父类公有成员继承后变为子类保护成员
共有继承:父类成员继承后属性不变