.NET适配器模式讲解

适配器模式简介:

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

在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

适配器模式结构图:

引入实例进行说明:

以日志记录程序为Demo说明,在任何一套软件中都会有对应的日志管理模块,假如如果我们在开发软件中的日记记录采用第三方的日志组件进行日志记录,它采用的是Log.Write("写日志");的方式我们的程序在开发中,大量实例化日记记录对象,采用的Log.Write()方式进行日志记录,但是现在第三方的日志组件现在不免费了,需要收费了,于是我们打算使用一种新的日志管理模块,只不过它提供给我们的API接口是采用Log.WriteLog("新的写日志的方式");进行日志记录。这个时候问题就出现了,如何应对这种迁移的变化

类适配器模式

1.原来日志的接口,采用的是Write(“写日志”);方法

  /// <summary>
  /// 原来的日志记录接口
  /// </summary>
  public interface ILogTarget
  {
    /// <summary>
    /// 原来的写日志方法
    /// </summary>
    void Write(string info);
  }

2.然而现在的写日志的接口,采用的是WriteLog("写日志");里面实现了写日志的新的方式:将日志写到文件中,数据库中

  /// <summary>
  /// 抽象写日志类
  /// </summary>
  public abstract class LogAdaptee
  {
    /// <summary>
    /// 写日志
    /// </summary>
    public abstract void WriteLog(string info);
  }
  /// <summary>
  /// 写文件日志记录
  /// </summary>
  public class FileLog:LogAdaptee
  {
    /// <summary>
    /// 写日志到文件中
    /// </summary>
    public override void WriteLog(string info)
    {
      Console.WriteLine("记录到文本文件:"+info);
    }
  }
  /// <summary>
  /// 往数据库中写日志
  /// </summary>
  public class DatabaseLog:LogAdaptee
  {
    /// <summary>
    /// 重写写日志方法
    /// </summary>
    public override void WriteLog(string info)
    {
      Console.WriteLine("记录到数据库:"+info);
    }
  }

3.如何使用者两个新对象中的方式,替换原来的写日志的方式?

  /// <summary>
  /// 采用新的写日志的方式,写入到数据库中
  /// </summary>
  public class DatabaseLogAdapter:DatabaseLog,ILogTarget
  {
    /// <summary>
    /// 在重写ILogTarget接口中的的Write方法里面调用新的写日志的方式WriteLog
    /// </summary>
    public void Write(string info)
    {
      WriteLog(info);
    }
  }

  /// <summary>
  /// 采用新的写日志的方式,写入到文本文件
  /// </summary>
  public class FileLogAdapter : FileLog, ILogTarget
  {
    /// <summary>
    /// 在重写ILogTarget接口中的的Write方法里面调用新的写日志的方式WriteLog
    /// </summary>
    public void Write(string info)
    {
      this.WriteLog(info);
    }
  }

4.调用依据使用的原来写日志的方法,但是确实使用的新的写日志的方式:

  /// <summary>
  /// 类 适配器模式(Adapter Pattern)
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      ILogTarget dbLog = new DatabaseLogAdapter();
      dbLog.Write("程序启动成功");
      dbLog = new FileLogAdapter();
      dbLog.Write("程序启动成功");
    }
  }

对象适配器模式

1.方式采用的是类适配器的方式实现了新的日志功能的迁移变化,下面我们使用对象适配器,可以区别发现两种方式的特别之处。原来写日志的方法依旧不变:Write("写日志");

  /// <summary>
  /// 原来的日志记录接口
  /// </summary>
  public interface ILogTarget
  {
    /// <summary>
    /// 原来的写日志方法
    /// </summary>
    void Write(string info);
  }

2.现在的写日志的接口,采用的是WriteLog("写日志");里面实现了写日志的新的方式:将日志写到文件中,数据库中:

  /// <summary>
  /// 抽象写日志类
  /// </summary>
  public abstract class LogAdaptee
  {
    /// <summary>
    /// 写日志
    /// </summary>
    public abstract void WriteLog(string info);
  }
  /// <summary>
  /// 写文件日志记录
  /// </summary>
  public class FileLog:LogAdaptee
  {
    /// <summary>
    /// 写日志到文件中
    /// </summary>
    public override void WriteLog(string info)
    {
      Console.WriteLine("记录到文本文件:"+info);
    }
  }
  /// <summary>
  /// 往数据库中写日志
  /// </summary>
  public class DatabaseLog:LogAdaptee
  {
    /// <summary>
    /// 重写写日志方法
    /// </summary>
    public override void WriteLog(string info)
    {
      Console.WriteLine("记录到数据库:"+info);
    }
  }

3.上面我们添加了FileLogAdapter 类,DatabaseLogAdapter类,继承了FileLog,DatabaseLog, ILogTarget接口,重写Write方法里面调用新的写日志的方式WriteLog,使用这样的方式进行了迁移变化。下面使用对象适配:

  /// <summary>
  /// 对象适配,继承ILogTarget,里面有LogAdaptee抽象日志类对象。
  /// </summary>
  public class LogAdapter:ILogTarget
  {
    /// <summary>
    /// 抽象写日志类
    /// </summary>
    private LogAdaptee _adaptee;

    public LogAdapter(LogAdaptee adaptee)
    {
      this._adaptee = adaptee;
    }

    public void Write(string info)
    {
      _adaptee.WriteLog(info);
    }
  }

4.在程序中的调用:

  /// <summary>
  /// 对象适配器模式(Adapter Pattern)
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      ILogTarget dbLog = new LogAdapter(new DatabaseLog());
      dbLog.Write("程序启动成功");
      ILogTarget fileLog = new LogAdapter(new FileLog());
      fileLog.Write("程序启动成功");
    }
  }

比较两者的迁移变化,在类适配方式中,我们得到的适配器类DatabaseLogAdapter和FileLogAdapter具有它所继承的父类的所有的行为,同时也具有接口ILogTarget的所有行为,这样其实是违背了面向对象设计原则中的类的单一职责原则,而对象适配器则更符合面向对象的精神,所以在实际应用中不太推荐类适配这种方式。假设我们要适配出来的类在记录日志时同时写入文件和数据库,那么用对象适配器我们会这样去写:

  /// <summary>
  /// 对象适配,继承ILogTarget,里面有LogAdaptee抽象日志类对象。
  /// </summary>
  public class LogAdapter:ILogTarget
  {
    /// <summary>
    /// 抽象写日志类
    /// </summary>
    private LogAdaptee _adapteed;

    /// <summary>
    /// 抽象写日志类
    /// </summary>
    private LogAdaptee _adapteef;

    public LogAdapter(LogAdaptee adapteed, LogAdaptee adapteef)
    {
      this._adapteed = adapteed;
      this._adapteef = adapteef;
    }

    public void Write(string info)
    {
      _adapteed.WriteLog(info);
      _adapteef.WriteLog(info);
    }
  }

调用:

  /// <summary>
  /// 对象适配器模式(Adapter Pattern)
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      //同时写日志到文件和数据库
      ILogTarget dbLog = new LogAdapter(new FileLog(), new DatabaseLog());
      dbLog.Write("程序启动成功");
    }
  }

如果改用类适配器:我们难道使用这样的写法达到目的?

  public class DatabaseLogAdapter : DatabaseLog, FileLog, ILogTarget
  {
    public void Write(string info)
    {
      this.WriteLog(info);
    }
  }

结果肯定是不能的,一个类不能具有多个基类,这样写明细有错误。所有针对不同的情况,我们应该采用合适的方式去进行适配调度。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • php适配器模式介绍

    要点: 1. 适配器模式主要应用于"希望复用一些现存的类,但是接口又与复用环境要求不一致的情况",在遗留代码复用.类库迁移等方面非常有用. 2. 适配器模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用"多继承"的实现方式,带来了不良的高耦合,所以一般不推荐使用.对象适配器采用"对象组合"的方式,更符合松耦合精神. 实现: 类的适配器模式结构图(继承) 对象的适配器模式结构图(组合) (对象适配器的代码实现) Target:定义Cli

  • php设计模式 Adapter(适配器模式)

    复制代码 代码如下: <?php /** * 适配器模式 * * 将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作 */ // 这个是原有的类型 class OldCache { public function __construct() { echo "OldCache construct<br/>"; } public function store($key,$value) { echo "OldCach

  • PHP设计模式之适配器模式代码实例

    目标: 可将一个类的接口转换成客户希望的另外一个接口,使得原本不兼容的接口能够一起工作.通俗的理解就是将不同接口适配成统一的API接口. 角色: Target适配目标,该角色定义把其他类转换为何种接口,也就是我们的期望接口. Adaptee被适配者,就是需要被适配的接口. Adapter适配器,其他的两个角色都是已经存在的角色,而适配器角色是需要新建立的,它用来对Adaptee与Target接口进行适配. 应用场景: 如数据操作有mysql.mysqli.pdo.sqlite.postgresq

  • Java设计模式之适配器模式(Adapter模式)介绍

    适配器模式定义:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 为何使用适配器模式 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口. 怎么办? 使用Adapter,在这两种接口之间创建一个混合接口(混血儿). 如何使用适配器模式 实现Adapter方式,其实"think in Java"的"类再生&quo

  • c# 适配器模式

    结构图: 客户可以对接的接口类: 复制代码 代码如下: class Target { public virtual void Request() { Console.WriteLine("普通请求!"); } } 客户需要使用适配器才能使用的接口: 复制代码 代码如下: class Adaptee { public void SpecialRequest() { Console.WriteLine("特殊请求!"); } } 适配器的定义:继承与Target类 复制

  • Python设计模式编程中Adapter适配器模式的使用实例

    将一个类的接口转换成客户希望的另外一个接口.使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 应用场景:希望复用一些现存的类,但是接口又与复用环境要求不一致. 模式特点:将一个类的接口转换成为客户希望的另外一个接口. 分类:类适配器(通过多重继承).对象适配器. 来通过例子说明,下面是用户通过适配器使用一个类的方法 class Target: def Request(): print "common request." class Adaptee(Target): def S

  • c#设计模式 适配器模式详细介绍

    后续内容将包括以下结构模式: 适配器模式(Adapter):Match interfaces of different classes合成模式(Composite):A tree structure of simple and composite objects装饰模式(Decorator):Add responsibilities to objects dynamically代理模式(Proxy):An object representing another object享元模式(Flywei

  • 浅析php适配器模式(Adapter)

    前几篇介绍了设计模式的特性并且详细讲解了4种创建型模式,创建型模式是负责如何产生对象实例的,接下来讲讲结构型模式. 一.什么是结构型模式? 结构型模式是解析类和对象的内部结构和外部组合,通过优化程序结构解决模块之间的耦合问题. 二.结构型模式的种类: 适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式 1. 适配器模式(Adapter) 将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作. 应用场景:老代码接口不适应

  • Java设计模式之适配器模式简介

    本文举例说明两种适配器模式,即类适配模式和对象适配模式,详情如下: 1.类适配模式: 举个例子来说明:在地球时代,所有坐骑都是只能跑,不能飞的,而现在很多坐骑在地球都可以飞了.假设,地球时代的坐骑只能跑,而现在的坐骑不仅能飞还能跑,我们可以用类适配模式来实现. 这里需要注意的是,适配器继承源类,实现目标接口. 示例代码如下: package adapter; /** * DOC 源 * */ public class Sources { public void run() { System.ou

  • C++设计模式之适配器模式

    生活中的适配器 买笔记本电脑,买手机时,都有一个电源适配器,电源适配器又叫外置电源,是小型便携式电子设备及电子电器的供电电压变换设备,常见于手机,笔记本电脑上.它的作用是将家里的220V高电压转换成这些电子产品能工作的5V~20V左右稳定的低电压,使它们能正常工作.就是说,如果没有这个电源适配器,我们的手机和电脑就不能进行充电了. 之前同事去日本出差,由于工作需要,就将自己的笔记本带过去了.到了的当晚就悲剧了,笔记本无法使用.由于日本的居民用电电压是110V,而中国是220V,同事的笔记本是22

随机推荐