C#设计模式编程中运用适配器模式结构实战演练

 更新时间:2016年02月17日 16:05:30   作者:Libing  
这篇文章主要介绍了C#设计模式编程中运用适配器模式结构实战演练,并总结了适配器模式的优缺点和适用场景以及.NET框架中的应用,需要的朋友可以参考下

 在实际的软件系统设计和开发中,为了完成某项工作需要购买一个第三方的库来加快开发。这带来一个问题,在应用程序中已经设计好的功能接口,与这个第三方提供的接口不一致。为了使得这些接口不兼容的类可以在一起工作,适配器模式提供了一种接口的适配机制。


  适配器模式的设计思想在生活中经常会应用到,如我们在给手机充电的时候,不可能直接在220V电源上直接充电,而是用手机充电器转换成手机需要的电压才可以正常充电,否则就不可以完成充电,这个充电器就起到了适配的作用。

适配器模式结构实现

1.类适配器结构实现

2016217155956456.png (367×596)

ITarget.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
 public interface ITarget
 {
  void Request();
 }
}  Adaptee.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
 public class Adaptee
 {
  public void SpecificRequest()
  {
   Console.WriteLine("Called SpecificRequest()");
  }
 }
}  Adapter.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
 public class Adapter : Adaptee, ITarget
 {
  public void Request()
  {
   this.SpecificRequest();
  }
 }
}  Client.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
 public class Client
 {
  static void Main(string[] args)
  {
   ITarget t = new Adapter();
   t.Request();
  }
 }
}  

运行输出:

Called SpecificRequest()
请按任意键继续. . .

2.对象适配器结构实现

  Client需要调用Request方法,而Adaptee并没有该方法,为了使Client能够使用Adaptee类,需要提供一个类Adapter。这个类包含了一个Adaptee的实例,将Client与Adaptee衔接起来。

ITarget.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
 public interface ITarget
 {
  void Request();
 }
}  

Target.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
 public class Target : ITarget
 {
  public virtual void Request()
  {
   Console.WriteLine("Called Target Request()");
  }
 }
}  

Adaptee.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
 public class Adaptee
 {
  public void SpecificRequest()
  {
   Console.WriteLine("Called SpecificRequest()");
  }
 }
} 

 Adapter.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
 public class Adapter : Target
 {
  private Adaptee _adaptee = new Adaptee();

  public override void Request()
  {
   _adaptee.SpecificRequest();
  }
 }
} 

 Client.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
 public class Client
 {
  static void Main(string[] args)
  {
   ITarget t = new Adapter();
   t.Request();
  }
 }
}


适配器模式实践应用

以手机充电的电源适配器为例,用适配器模式的解决方案。

2016217160138027.png (367×596)

1.类适配器结构实现
ITarget.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
 public interface ITarget
 {
  void GetPower();
 }
}  Power.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
 public class Power
 {
  public void GetPower220V()
  {
   Console.WriteLine("从电源中得到220V的电压");
  }
 }
}  Adapter.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
 public class Adapter : Power, ITarget
 {
  public void GetPower()
  {
   this.GetPower220V();
   Console.WriteLine("得到手机的充电电压!");
  }
 }
}  Client.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
 public class Client
 {
  static void Main(string[] args)
  {
   Console.WriteLine("手机:");
   ITarget t = new Adapter();
   t.GetPower();
  }
 }
}  

运行输出:

手机:
从电源中得到220V的电压
得到手机的充电电压!
请按任意键继续. . .

2.对象适配器结构实现
ITarget.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
 public interface ITarget
 {
  void GetPower();
 }
} 

 Power.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
 public class Power
 {
  public void GetPower220V()
  {
   Console.WriteLine("从电源中得到220V的电压");
  }
 }
} 

 Adapter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
 public class Adapter : ITarget
 {
  public Power _power;
  public Adapter(Power power)
  {
   this._power = power;
  }

  /// <summary>
  /// 得到想要的电压
  /// </summary>
  public void GetPower()
  {
   _power.GetPower220V();
   Console.WriteLine("得到手机的充电电压!");
  }
 }
} 

 Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
 public class Client
 {
  static void Main(string[] args)
  {
   Console.WriteLine("手机:");
   ITarget t = new Adapter(new Power());
   t.GetPower();
  }
 }
}

适配器模式的优缺点
在引言部分已经提出,适配器模式用来解决现有对象与客户端期待接口不一致的问题,下面详细总结下适配器两种形式的优缺点。
1.类的适配器模式:
优点:
可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”
可以重新定义Adaptee(被适配的类)的部分行为,因为在类适配器模式中,Adapter是Adaptee的子类
仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例(这个即是优点也是缺点)。
缺点:
用一个具体的Adapter类对Adaptee和Target进行匹配,当如果想要匹配一个类以及所有它的子类时,类的适配器模式就不能胜任了。因为类的适配器模式中没有引入Adaptee的实例,光调用this.SpecificRequest方法并不能去调用它对应子类的SpecificRequest方法。
采用了 “多继承”的实现方式,带来了不良的高耦合。
2.对象的适配器模式
优点:
可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”(这点是两种实现方式都具有的)
采用 “对象组合”的方式,更符合松耦合。
缺点:
使得重定义Adaptee的行为较困难,这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。

使用场景
在以下情况下可以考虑使用适配器模式:
系统需要复用现有类,而该类的接口不符合系统的需求
想要建立一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
对于对象适配器模式,在设计里需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。

.NET中适配器模式的实现
1.适配器模式在.NET Framework中的一个最大的应用就是COM Interop。COM Interop就好像是COM和.NET之间的一座桥梁(关于COM互操作更多内容可以参考我的互操作系列)。COM组件对象与.NET类对象是完全不同的,但为了使.NET程序像使用.NET对象一样使用COM组件,微软在处理方式上采用了Adapter模式,对COM对象进行包装,这个包装类就是RCW(Runtime Callable Wrapper)。RCW实际上是runtime生成的一个.NET类,它包装了COM组件的方法,并内部实现对COM组件的调用。如下图所示:

2016217160319899.png (784×333)

2..NET中的另外一个适配器模式的应用就是DataAdapter。ADO.NET为统一的数据访问提供了多个接口和基类,其中最重要的接口之一是IdataAdapter。DataAdpter起到了数据库到DataSet桥接器的作用,使应用程序的数据操作统一到DataSet上,而与具体的数据库类型无关。甚至可以针对特殊的数据源编制自己的DataAdpter,从而使我们的应用程序与这些特殊的数据源相兼容。

相关文章

  • 实例解析C#设计模式编程中简单工厂模式的使用

    实例解析C#设计模式编程中简单工厂模式的使用

    这篇文章主要介绍了C#设计模式编程中简单工厂模式的使用,文中也举了在.NET框架下简单工厂模式的实现例子,需要的朋友可以参考下
    2016-02-02
  • C#调用FFmpeg操作音视频的实现示例

    C#调用FFmpeg操作音视频的实现示例

    本文主要介绍了C#调用FFmpeg操作音视频的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C#异步使用需要注意的几个问题

    C#异步使用需要注意的几个问题

    C#使用异步方法中,使用一下关键词的时候徐注意一些问题,比如async 方法需在其主体中具有 await 关键字,否则它们将永不暂停,接下来文字里将为大家举例说明
    2021-09-09
  • C# wpf Grid中实现控件拖动调整大小的示例代码

    C# wpf Grid中实现控件拖动调整大小的示例代码

    本文主要介绍了C# wpf Grid中实现控件拖动调整大小的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • C#中缓存System.Web.Caching用法总结

    C#中缓存System.Web.Caching用法总结

    本文详细讲解了C#中缓存System.Web.Caching的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#使用CefSharp实现内嵌网页详解

    C#使用CefSharp实现内嵌网页详解

    这篇文章主要介绍了C# WPF里怎么使用CefSharp嵌入一个网页,并给出一个简单示例演示C#和网页(JS)的交互实现,感兴趣的小伙伴可以了解一下
    2023-04-04
  • 在C#中如何获取程序集

    在C#中如何获取程序集

    某一天我正在写一些反射代码,目的是遍历所有的程序集来查找一个特定的接口,然后在Startup中调用其上的一个方法,这篇文章主要介绍了在C#中如何获取程序集,需要的朋友可以参考下
    2024-03-03
  • 基于C#实现网络爬虫 C#抓取网页Html源码

    基于C#实现网络爬虫 C#抓取网页Html源码

    这篇文章主要为大家详细介绍了基于C#实现网络爬虫的相关资料,即C#抓取网页Html源码,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • C#中的预定义类型与引用类型

    C#中的预定义类型与引用类型

    这篇文章介绍了C#中的预定义类型与引用类型,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • c# 模拟线性回归的示例

    c# 模拟线性回归的示例

    这篇文章主要介绍了c# 模拟线性回归的示例,帮助大家利用c#进行机器学习,感兴趣的朋友可以了解下
    2020-10-10

最新评论