http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 10466|回复: 4

[学习心得] C#适配器模式

[复制链接]
发表于 2019-1-5 10:45:28 | 显示全部楼层 |阅读模式
本帖最后由 惜 于 2019-1-5 10:45 编辑

          结构模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构。结构模式描述两种不同的
东西:类与类的实例。根据这一点,结构模式可以分为类的结构模式和对象的结构模式。

后续内容将包括以下结构模式:

            适配器模式(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
            享元模式   (Flyweight): A fine-grained instance used for efficient sharing
            门面模式   (Facade):    A single class that represents an entire subsystem
            桥梁模式   (Bridge):      Separates an object interface from its implementation

一 、  适配器 (Adapter ) 模式

       适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。

名称由来

       这很像变压器(Adapter),变压器把一种电压变换成另一种电压。美国的生活用电电压是 110V,而中国的电
压是 220V。如果要在中国使用美国电器,就必须有一个能把 220V 电压转换成 110V 电压的变压器。这个变压
器就是一个 Adapter。

       Adapter 模式也很像货物的包装过程:被包装的货物的真实样子被包装所掩盖和改变,因此有人把这种模式叫
做包装(Wrapper)模式。事实上,大家经常写很多这样的 Wrapper 类,把已有的一些类包装起来,使之有能
满足需要的接口。

适配器模式的两种形式

    适配器模式有类的适配器模式和对象的适配器模式两种。我们将分别讨论这两种 Adapter 模式。

二 、  类的 Adapter  模式的结构


1.png


       由图中可以看出,Adaptee 类没有 Request 方法,而客户期待这个方法。为了使客户能够使用 Adaptee 类,
提供一个中间环节,即类 Adapter 类,Adapter 类实现了 Target 接口,并继承自 Adaptee,Adapter 类的
Request 方法重新封装了 Adaptee 的 SpecificRequest 方法,实现了适配的目的。

因为 Adapter 与 Adaptee 是继承的关系,所以这决定了这个适配器模式是类的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。因为 C#不支持多继承,所以 Target 必须是接口,不可以是类。

源(Adaptee)角色:需要适配的类。

适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类

三 、  类的 Adapter  模式示意性实现

下面的程序给出了一个类的 Adapter 模式的示意性的实现:

[C#] 纯文本查看 复制代码
using System;

namespace ConsoleApplication1
{

    /// <summary>
    /// 我们要实现的接口
    /// </summary>
    interface ITarget
    {
        // Methods
        void Request();
    }

    /// <summary>
    /// 我们要封装的类
    /// </summary>
    class Adaptee
    {
        // Methods
        public void SpecificRequest()
        {
            Console.WriteLine("Called SpecificRequest()");
        }
    }

    /// <summary>
    /// 实际封装实现的类
    /// </summary>
    class Adapter : Adaptee, ITarget
    {
        // Implements ITarget interface
        public void Request()
        {
            // Possibly do some data manipulation
            // and then call SpecificRequest
            this.SpecificRequest();
        }
    }

    /// <summary>
    /// 调用
    /// </summary>
    public class Client
    {
        public static void Main(string[] args)
        {
            // Create adapter and place a request
            ITarget t = new Adapter();
            t.Request();
        }
    }
}


四 、  对象的 Adapter  模式的结构 :

2.png

      从图中可以看出:客户端需要调用 Request 方法,而 Adaptee 没有该方法,为了使客户端能够使用 Adaptee
类,需要提供一个包装(Wrapper)类 Adapter。这个包装类包装了一个 Adaptee 的实例,从而将客户端与
Adaptee 衔接起来。由于 Adapter 与 Adaptee 是委派关系,这决定了这个适配器模式是对象的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

源(Adaptee)角色:需要适配的类。

适配器(Adapter)角色:通过在内部包装(Wrap)一个 Adaptee 对象,把源接口转换成目标接口。

五 、  对象的 Adapter  模式示意性实现

下面的程序给出了一个类的 Adapter 模式的示意性的实现:

[C#] 纯文本查看 复制代码
// Adapter pattern -- Structural example

using System;

namespace ConsoleApplication1
{
    /// <summary>
    /// 我们要继承的基类
    /// </summary>
    class Target
    {
        /// <summary>
        /// 虚方法 在派生类中 重写
        /// </summary>
        public virtual void Request()
        {
            // Normal implementation goes here
        }
    }

    /// <summary>
    /// 我们实现重写封装的类
    /// </summary>
    class Adapter : Target
    {
        // 实列对象
        private Adaptee adaptee = new Adaptee();
        // 重写基类的方法
        public override void Request()
        {
            // Possibly do some data manipulation
            // and then call SpecificRequest
            adaptee.SpecificRequest();
        }
    }
    /// <summary>
    /// 我们要封装的类
    /// </summary>
    class Adaptee
    {
        // Methods
        public void SpecificRequest()
        {
            Console.WriteLine("Called SpecificRequest()");
        }
    }
    /// <summary>
    /// 调用
    /// </summary>
    public class Client
    {
        public static void Main(string[] args)
        {
            // Create adapter and place a request
            Target t = new Adapter();
            t.Request();
        }
    }
}

六 、  在什么情况下使用适配器模式

在以下各种情况下使用适配器模式:

1、 系统需要使用现有的类,而此类的接口不符合系统的需要。

2、 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的
      类一起工作。这些源类不一定有很复杂的接口。

3、 (对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一
      个子类做一个适配器,而这不太实际。

七 、  一个实际应用 Adapter  模式的例子

下面的程序演示了 Class Adapter 与 Object Adapter 的应用。

[C#] 纯文本查看 复制代码
// Example of implementing the Adapter pattern
using System;

/// <summary>
/// 我们要实现的接口
/// </summary>
public interface ICar
{
    void Drive();
}

/// <summary>
/// 继承 实现 ICar
/// </summary>
public class CToyota : ICar
{
    public void Drive()
    {
        Console.WriteLine("Vroom Vroom, we're off in our Toyota ");
    }
}
/// <summary>
///需要封装的类
/// </summary>
public class CCessna
{
    public void Fly()
    {
        Console.WriteLine("Static runup OK, we're off in our C172 ");
    }
}

/// <summary>
/// 我们继承了CCessna ICar (类的Adapter)
/// </summary>
public class CDrivableCessna : CCessna, ICar
{
    /// <summary>
    /// 在这里实现了Drive 并在Drive里面 调用 CCessna =>Fly
    /// </summary>
    public void Drive() { base.Fly(); }
}

/// <summary>
/// 继承 实现 实例化后调用(对象的Adapter)
/// </summary>
public class CDrivableCessna2 : ICar
{
    private CCessna m_oContained;
    public CDrivableCessna2()
    {
        m_oContained = new CCessna();
    }
    public void Drive() { m_oContained.Fly(); }
}

/// <summary>
/// 调用
/// </summary>
public class Client
{
    public static void Main(string[] args)
    {
        ICar oCar = new CToyota();
        Console.Write("Class Adapter: Driving an Automobile ");
        oCar.Drive();

        oCar = new CDrivableCessna();
        Console.Write("Driving a Cessna ");
        oCar.Drive();

        oCar = new CDrivableCessna2();
        Console.Write(" Object Adapter: Driving a Cessna ");
        oCar.Drive();
    }
}



















1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2019-1-5 11:04:59 | 显示全部楼层
强烈支持楼主ing……
发表于 2019-1-5 11:29:47 | 显示全部楼层
我只是路过打酱油的。
发表于 2019-1-5 14:13:24 | 显示全部楼层
强烈支持楼主ing……
发表于 2019-1-5 21:02:53 | 显示全部楼层
我只是路过打酱油的。
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-12-22 19:50

© 2014-2021

快速回复 返回顶部 返回列表