[设计模式] 设计模式课程(十三)--适配器模式

概述

  • 由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但新环境要求的接口是这些现存对象所不满足的
  • 如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?
  • 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)的特性
  • 相比类适配器,对象适配器灵活性更高(指针可以指向不同对象)

场景

  • Java JDK 1.1使用了Enumeration接口,1.2中提供了Iterator接口,想要使用1.2 的JDK,则要讲以前系统的Enumeration接口转化为Iterator接口
  • 在Linux上运行Windows程序
  • Java中的jdbc

示例1

 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

示例2

 1 #include <string>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 class Target {
 7  public:
 8   virtual ~Target() = default;
 9 
10   virtual string Request() const {
11     return "Target: The default target's behavior.";
12   }
13 };
14 
15 /**
16  * The Adaptee contains some useful behavior, but its interface is incompatible
17  * with the existing client code. The Adaptee needs some adaptation before the
18  * client code can use it.
19  */
20 class Adaptee {
21  public:
22   string SpecificRequest() const {
23     return ".eetpadA eht fo roivaheb laicepS";
24   }
25 };
26 
27 /**
28  * The Adapter makes the Adaptee's interface compatible with the Target's
29  * interface.
30  */
31 class Adapter : public Target {
32  private:
33   Adaptee *adaptee_;
34 
35  public:
36   Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
37   string Request() const override {
38     string to_reverse = this->adaptee_->SpecificRequest();
39     reverse(to_reverse.begin(), to_reverse.end());
40     return "Adapter: (TRANSLATED) " + to_reverse;
41   }
42 };
43 
44 /**
45  * The client code supports all classes that follow the Target interface.
46  */
47 void ClientCode(const Target *target) {
48   std::cout << target->Request();
49 }
50 
51 int main() {
52   std::cout << "Client: I can work just fine with the Target objects:
";
53   Target *target = new Target;
54   ClientCode(target);
55   std::cout << "

";
56   Adaptee *adaptee = new Adaptee;
57   std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:
";
58   std::cout << "Adaptee: " << adaptee->SpecificRequest();
59   std::cout << "

";
60   std::cout << "Client: But I can work with it via the Adapter:
";
61   Adapter *adapter = new Adapter(adaptee);
62   ClientCode(adapter);
63   std::cout << "
";
64 
65   delete target;
66   delete adaptee;
67   delete adapter;
68 
69   return 0;
70 }
View Code

参考 

UML图

https://www.cnblogs.com/jiangds/p/6596595.html

protected成员

http://c.biancheng.net/view/252.html

私有成员:只能在类内使用

保护成员:类内,继承类内可以使用

共有成员:所有地方都可使用 

私有继承:父类成员继承后变为子类私有成员

保护继承:父类公有成员继承后变为子类保护成员

共有继承:父类成员继承后属性不变

原文地址:https://www.cnblogs.com/cxc1357/p/12313115.html