设计模式之Adapter适配器设计模式


意图intent:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适用性

  • 你想使用一个已经存在的类,而它的接口不符合你的需求。
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

 

Definition

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. 

 

Participants

    The classes and/or objects participating in this pattern are:

  • Target   (ChemicalCompound)
    • defines the domain-specific interface that Client uses.
  • Adapter   (Compound)
    • adapts the interface Adaptee to the Target interface.
  • Adaptee   (ChemicalDatabank)
    • defines an existing interface that needs adapting.
  • Client   (AdapterApp)
    • collaborates with objects conforming to the Target interface.

Adapter模式有两种实现形式,一种是所谓的Adapter Class,另一种是所谓的Adapter Object

前一种是通过多重继承来实现的,也即Adapter继承了AdapteeTarget来实现,也即在类Adapter中,通过调用Adaptee中的函数来替换(覆盖)掉Target的实现。另一种是Adapter中有一个成员变量是Adaptee,然后也是通过覆盖掉Target来实现的。现在很多语言都不支持多继承了,所以实际上在c#java中都只能通过后一种方法来实现了。当然了,后一种继承确实也是比前一种要好,因为前一种设计耦合性太高了。

Sample code in C#

This structural code demonstrates the Adapter pattern which maps the interface of one class onto another so that they can work together. These incompatible classes may come from different libraries or frameworks.

// Adapter pattern -- Structural example

 

using System;

namespace DoFactory.GangOfFour.Adapter.Structural
{

  // Mainapp test application

  class MainApp
  {
    static void Main()
    {
      // Create adapter and place a request
      Target target = new Adapter();
      target.Request();

      // Wait for user
      Console.Read();
    }
  }

  // "Target"

  class Target
  {
    public virtual void Request()
    {
      Console.WriteLine("Called Target Request()");
    }
  }

  // "Adapter"

  class Adapter : Target
  {
    private Adaptee adaptee = new Adaptee();

    public override void Request()
    {
      // Possibly do some other work
      // and then call SpecificRequest
      adaptee.SpecificRequest();
    }
  }

  // "Adaptee"

  class Adaptee
  {
    public void SpecificRequest()
    {
      Console.WriteLine("Called SpecificRequest()");
    }
  }
}


Output

Called SpecificRequest()

 

 

This real-world code demonstrates the use of a legacy chemical databank. Chemical compound objects access the databank through an Adapter interface.

// Adapter pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.Adapter.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      // Non-adapted chemical compound
      Compound stuff = new Compound("Unknown");
      stuff.Display();
      
      // Adapted chemical compounds
      Compound water = new RichCompound("Water");
      water.Display();

      Compound benzene = new RichCompound("Benzene");
      benzene.Display();

      Compound alcohol = new RichCompound("Alcohol");
      alcohol.Display();

      // Wait for user
      Console.Read();
    }
  }

  // "Target"

  class Compound
  {
    protected string name;
    protected float boilingPoint;
    protected float meltingPoint;
    protected double molecularWeight;
    protected string molecularFormula;

    // Constructor
    public Compound(string name)
    {
      this.name = name;
    }

    public virtual void Display()
    {
      Console.WriteLine("/nCompound: {0} ------ ", name);
    }
  }

  // "Adapter"

  class RichCompound : Compound
  {
    private ChemicalDatabank bank;

    // Constructor
    public RichCompound(string name) : base(name)
    {
    }

    public override void Display()
    {
      // Adaptee
      bank = new ChemicalDatabank();
      boilingPoint = bank.GetCriticalPoint(name, "B");
      meltingPoint = bank.GetCriticalPoint(name, "M");
      molecularWeight = bank.GetMolecularWeight(name);
      molecularFormula = bank.GetMolecularStructure(name);

      base.Display();
      Console.WriteLine(" Formula: {0}", molecularFormula);
      Console.WriteLine(" Weight : {0}", molecularWeight);
      Console.WriteLine(" Melting Pt: {0}", meltingPoint);
      Console.WriteLine(" Boiling Pt: {0}", boilingPoint);
    }
  }

  // "Adaptee"

  class ChemicalDatabank
  {
    // The Databank 'legacy API'
    public float GetCriticalPoint(string compound, string point)
    {
      float temperature = 0.0F ;

      // Melting Point
      if (point == "M")
      {
        switch (compound.ToLower())
        {
          case "water" : temperature = 0.0F ; break;
          case "benzene" : temperature = 5.5F ; break;
          case "alcohol" : temperature = -114.1F ; break;
        }
      }
      // Boiling Point
      else
      {
        switch (compound.ToLower())
        {
          case "water" : temperature = 100.0F ; break;
          case "benzene" : temperature = 80.1F ; break;
          case "alcohol" : temperature = 78.3F ; break;
        }
      }
      return temperature;
    }

    public string GetMolecularStructure(string compound)
    {
      string structure = "";

      switch (compound.ToLower())
      {
        case "water" : structure = "H20"; break;
        case "benzene" : structure = "C6H6"; break;
        case "alcohol" : structure = "C2H6O2"; break;
      }
      return structure;
    }

    public double GetMolecularWeight(string compound)
    {
      double weight = 0.0;
      switch (compound.ToLower())
      {
        case "water" : weight = 18.015; break;
        case "benzene" : weight = 78.1134; break;
        case "alcohol" : weight = 46.0688; break;
      }
      return weight;
    }
  }
}


Output


Compound: Unknown ------

Compound: Water ------
 Formula: H20
 Weight : 18.015
 Melting Pt: 0
 Boiling Pt: 100

Compound: Benzene ------
 Formula: C6H6
 Weight : 78.1134
 Melting Pt: 5.5
 Boiling Pt: 80.1

Compound: Alcohol ------
 Formula: C2H6O2
 Weight : 46.0688
 Melting Pt: -114.1
 Boiling Pt: 78.3

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值