`

设计模式之适配器模式

阅读更多

什么是设计模式

在软件开发的世界里,许多领域中的问题具有相似的特性。就像造房子一样,不管要盖一座购物中心,还是要盖一座假日酒店,它们之间都有基本上相似的工作步骤,都需要搭建梁柱,铺置房顶等工作。在做这些工作时都需要遵循某种特殊的技术要求,以使得房子的结构、承受能力达到合理,这些规则是前人经过精确的计算和失败的教训得来的。对于软件开发也一样,如果我们希望编写出来健壮、灵活的应用程序,也有必要进行精细的设计,并且可以通过遵循某种规则以达到这个目标。这些规则或者称之为技巧就是设计模式。

设计模式领域中有一本经典的著作:《Design Patterns: Elements of Reusable Object-Oriented Software》(即《设计模式》一书),由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。这几位作者常被称为“四人组(Gang of Four)”,而这本书也就被称为“四人组(或 GoF)”书。此书中介绍了23种设计模式,随着技术的不断发展,新的设计模式不断的被发现,但这23种设计模式是最值得学习和掌握的。 C#设计模式中将设计模式划分为以下5类:

  • 接口型模式
  • 职责型模式
  • 构造型模式
  • 操作型模式
  • 扩展型模式

各类别中包含的模式:

类别 包含的设计模式
接口型 适配器模式,外观模式,合成模式,桥接模式
职责型 单件模式,观察者模式,中介者模式,代理模式,职责链模式,享元模式
构造型 生成器模式,工厂方式模式,抽象工厂模式,原型模式,备忘录模式
操作型 模板方法模式,状态模式,策略模式,命令模式,解释器模式
扩展型 装饰模式,迭代器模式,访问者模式

适配器模式

一. 现实问题

在进行项目开发时,经常会发生类之间的调用关第,有可能存在以下两种情况:

1. 我们已经定义了类调用关系,例如类需要通过调用实现了某个接口的类来实现特定功能,而这个功能第三方类已经实现了,第三方类的方法签名可能与客户期望的签名不太一致。

2.这些类提供的方法可能只是完成了我们所需要的大部分功能,我们还要在此基础上执行一点点额外的操作;

二. 解决方案

以上两种问题实际上都是客户需要对提供功能的服务类的调用,可以有以下几种解决方案:

1. 直接在客户类里实例化服务类,进行方法调用,并且根据需要在调用后进行额外的处理。

2. 创建一个中介,将方法调用传递给中介,由中介请求服务类并执行额外操作。

比较而言,第二种方式更为合理,因为通过中介类的引处,降低了客户类和服务类的耦合,在服务类发生变化时,可以不影响到客户类。

三. 概念定义

对于这种问题,可以使用适配器模式。适配器模式的目的在于:如果客户需要使用某个类的服务,而这项服务是这个类用一个不同的接口提供的,那么,可以使用适配器为客户提供一个期望的接口。

存在两种适配器的形式:接口适配器(类适配器)和对象适配器。

四. 项目示例

1. 接口适配器

客户类需要通过对某个接口的调用来实现某个功能,而这个功能已经被服务类实现了。可以引入适配器类,该类继承自服务类并实现了客户端要调用的接口。

例如现在期望实现用户登录的同时更新最后活动时间的功能,约定客户类需要调用某个接口的方法实现该操作。此时发现已有现成的类(服务类)实现了用户登录的功能,但没有实现更新活动时间的操作,因此可以创建一个接口适配器。类关系图如下所示:

image

客户类代码如下(只定义了相应的方法,未编写实现):

/// <summary>
/// 客户类
/// </summary>
class Client
{
    public IUser User
    {
        get
        {
            throw new System.NotImplementedException();
        }
        set
        {
        }
    }
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="user">用户名称</param>
    /// <param name="lastActivityDate">最后活动日期</param>
    public void Login(string user, DateTime lastActivityDate)
    {
        User = new InterfaceAdapter();

        User.Login(user, lastActivityDate);
    }
}

接口定义如下:

interface IUser
{
    void Login(string name,DateTime lastActivityDate);
}

服务类定义如下:

/// <summary>
/// 服务类
/// </summary>
class Service
{
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="user">用户名称</param>
    public void UserLogin(string user)
    {
        throw new NotImplementedException();
    }
}

接口适配器定义如下:

class InterfaceAdapter : Service, IUser
{
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="name"></param>
    /// <param name="lastActivityDate"></param>
    public void Login(string name, DateTime lastActivityDate)
    {
        UserLogin(name);

        UpdateActivityDate(name, lastActivityDate);
    }

    private void UpdateActivityDate(string name, DateTime lastActivityDate)
    {
        throw new NotImplementedException();
    }
}

此时可以直接实例化Client类并完成登录调用,例如:

Client client = new Client();

client.Login("admin",DateTime.Now);

以上是接口适配器的示例,如果客户端不存在这样的一个接口,那么可以使用对象适配器。

2. 对象适配器

使用对象适配器时,需要创建客户类的一个子类,并重写相应的方法,在该适配器类中通过服务类完成相应的功能并执行其他操作,在执行客户类操作时可以通过适配器完成。但是需要注意把客户端相应的方法定义为virtual以能够重写。上述示例使用对象适配器的类关系图如下所示:

image 

ObjectAdapter定义如下:

class ObjectAdapter:Client
{
    internal Service Service
    {
        get;
        set;
    }

    public override void Login(string user, DateTime lastActivityDate)
    {
        Service.UserLogin(user);
        UpdateActivityDate(user, lastActivityDate);
    }

    private void UpdateActivityDate(string name, DateTime lastActivityDate)
    {
        throw new NotImplementedException();
    }
}

在执行用户登录时可以通过ObjectAdapter完成,例如:

Client client = new ObjectAdapter();

client.Login("admin",DateTime.Now);

和接口适配器相比,对象适配器更加脆弱,这主要是由于对象适配器没有引入接口,在服务类发生变化时,仍然需要修改客户端代码。

分享到:
评论

相关推荐

    Java设计模式之适配器模式

    ### Java设计模式之适配器模式详解 #### 引言 在软件开发中,我们经常遇到需要使用已有的类库,但这些类库的接口与我们的需求不匹配的情况。这时,适配器模式(Adapter Pattern)便能派上用场。适配器模式是一种...

    设计模式之适配器模式与外观模式demo

    在软件设计领域,设计模式是一种经过时间和实践验证的解决方案,用于解决常见的...这个"设计模式之适配器模式与外观模式demo"资源为学习和实践这两种模式提供了宝贵的实例,对于提升编程技能和设计思维具有积极意义。

    深入浅出设计模式之适配器模式与外观模式

    ### 深入浅出设计模式之适配器模式与外观模式 在软件工程领域,设计模式被广泛地应用于解决常见的编程问题。其中,《Head First 设计模式》是一本非常受欢迎的经典著作,它通过生动有趣的例子帮助读者理解并掌握...

    java设计模式之适配器模式

    适配器模式是一种在软件工程中广泛使用的结构型设计模式,它允许两个不兼容的接口之间进行通信。在Java中,适配器模式扮演着重要的角色,尤其在处理遗留代码或者第三方库集成时,能够有效地解决接口不匹配的问题。...

    设计模式之适配器模式Java实现和类设计图

    适配器模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,允许不兼容的接口之间进行通信。在这个Java实现中,我们将深入探讨适配器模式的两大类型:类适配器模式和对象适配器模式,并通过具体的代码示例和...

    设计模式之 适配器 Adapter C++ 源码

    设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式...

    设计模式之适配器模式(Adapter Pattern)

    适配器模式是软件设计模式中的一种,它的主要目的是解决接口不兼容问题,使得原本由于接口差异无法协同工作的类能够协同工作。在实际的软件开发过程中,我们常常遇到这样的情况:旧有的系统或第三方库提供了丰富的...

    设计模式之适配器模式.docx

    适配器模式是一种设计模式,它的主要目的是解决接口不兼容的问题,使得原本因接口差异而无法协同工作的类能够一起工作。适配器模式的核心思想是通过一个中间适配器类来转换不同接口,使得原有类(被适配者)能够符合...

    java设计模式之适配器模式.zip

    适配器模式是一种在软件设计中广泛使用的结构型设计模式,它的主要目的是使不兼容的接口之间能够进行通信。在Java编程中,适配器模式能够帮助我们复用已有的类,或者解决新旧系统之间的接口不匹配问题,从而提高代码...

    JAVA设计模式之适配器模式.docx

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在Java中,适配器模式被广泛应用于各种场景,如文件描述符的处理和框架的日志记录。下面我们将深入探讨适配器模式的核心概念、结构、使用场景...

    23钟设计模式之适配器模式

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在上述代码示例中,适配器模式被用来解决洗衣机(Wash)和电视机(Tv)与不同插座接口(SanXiangChaZuo 和 ErXiangChaZuo)之间的兼容性问题。...

    c++-设计模式之适配器模式(Adapter Pattern)

    适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个接口转换为客户端期望的另一个接口。适配器模式常用于解决由于接口不兼容而无法正常工作的类之间的协作问题。 适配器模式的组成 目标接口(Target...

    [结构型模式] head first 设计模式之适配器模式(Adapter)

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在软件工程中,当系统中存在一个已经存在的组件,但其接口不符合当前项目的需求时,适配器模式就能发挥作用。通过适配器,我们可以复用现有的...

Global site tag (gtag.js) - Google Analytics