C#设计模式之适配器模式与装饰器模式的实现

目录
  • 结构型设计模式
  • 适配器模式
    • 实现代码
    • 总结
  • 装饰器模式
    • 实现代码

结构型设计模式

创建型设计模式主要是为了解决创建对象的问题,而结构型设计模式则是为了解决已有对象的使用问题。

适配器模式

适配器模式比较好理解,因为在我们的日常生活中就很常见,如耳机转换线、充电器适配器、插座等,举个最常见的例子:

插座就是个适配器,将一个接口扩展为多个接口,将墙上的双孔接口转换为三孔接口。而这也就是适配器的作用:将一个接口转换为用户期望的另一个接口。

适配器的使用场景:

  • 需要使用第三方SDK的核心功能,但其接口或者功能不符合需求,这时可以使用适配器对其进行兼容和扩展
  • 随着业务发展,旧接口已经不能满足需求,但重写代价又太大,这时可以使用适配器对接口功能进行扩展

注意:适配器是对已有资源进行兼容和扩展,属于一种折中的方式,如果可以的话,尽量重构系统而不是使用适配器

继承器的实现有两种方式:继承组合,基于合成复用的原则,组合优于继承,所以应尽量使用组合的方式实现适配器。类图如下:

实现代码

//已有的旧接口,不兼容于现在的系统
    public interface IAmericanElectrictService
    {
        int Get110VElectric();
    }

    //adaptee,需要适配的SDK
    public class AmericanElectrictService : IAmericanElectrictService
    {
        public int Get110VElectric()
        {
            Console.WriteLine("美国的电压是110v,只能提供110V的电压");
            return 110;
        }
    }

    //已有接口,现在的系统需要使用这个接口
    public interface IChineseElectricService
    {
        int Get220VElectric();
    }

    //适配器,采取组合的方式
    //这里是为了适配已有接口,所以实现了这个接口
    public class AdapterPattern : IChineseElectricService
    {
        private readonly IAmericanElectrictService _service;

        public AdapterPattern(IAmericanElectrictService service)
        {
            this._service = service;
        }
        public int Get220VElectric()
        {
            var electric = this._service.Get110VElectric();
            Console.WriteLine("劈里啪啦劈里啪啦,经过一番操作,现在电压转换为220V的了");
            return electric + 110;
        }
    }

    //使用适配器,将110V电压转换成220V
    public class AdapterRunner : IRunner
    {
        public void Run()
        {
            //实际情况中,adaptee有可能是已有SDK,有可能是interface,通过IOC容器对应具体实现类
            var americanElectric = new AmericanElectrictService();
            var electric = americanElectric.Get110VElectric();
            Console.WriteLine($"获得了{electric}V电压");
            Console.WriteLine("使用适配器");
            var adapter = new AdapterPattern(americanElectric);
            electric = adapter.Get220VElectric();
            Console.WriteLine($"使用适配器后获得了{electric}V电压");
        }
    }
    //输出
    //------------------------------------
    //美国的电压是110v,只能提供110V的电压
    //获得了110V电压
    //使用适配器
    //美国的电压是110v,只能提供110V的电压
    //劈里啪啦劈里啪啦,经过一番操作,现在电压转换为220V的了
    //使用适配器后获得了220V电压

总结

优点:

  • 可以扩展和兼容现有类,灵活性高
  • 提高了类的复用,原本不能使用的类适配后能使用

缺点:

  • 适配器本质是套一层,如果使用过多,可能导致系统混乱,甚至出现套中套的复杂情况

装饰器模式

利用继承和组合,在不改变现有结构的情况下对功能进行扩展的模式称为装饰器模式

装饰器模式和适配器模式很像,但侧重点不一样。适配器的重心在于兼容已有系统,而装饰器的重心在于功能扩展。装饰器的类图如下:

上图中,基础装饰器继承抽象类,每个装饰器继承前一个装饰器,一步一步添加功能,并且所有装饰器都用到具体实现类,因为需要扩展具体功能。

这里其实就能看出一些装饰器和适配器的区别,适配器和装饰器都使用组合来包装已有类,不同的是装饰器用到了继承。装饰器的核心原则是里氏替换原则,即父类一定能被子类替换而不影响现有代码。

实现代码

//抽象基础类
public abstract class AbstractStudent
{
    public abstract void Study();
}

//具体实现类
public class Student : AbstractStudent
{
    public override void Study()
    {
        Console.WriteLine("我正在学习!!!");
    }
}

//基础装饰器,什么也不做
//注意,这里标记为抽象类,此后的装饰器以此为基础
public abstract class BaseDecorator : AbstractStudent
{
    private readonly AbstractStudent _student;
    public BaseDecorator(AbstractStudent student)
    {
        this._student = student;
    }
    //这里使用override还是Virtual取决于AbstractStudent基础类是抽象类还是接口
    public override void Study()
    {
        this._student.Study();
    }
}

//前缀装饰器,在调用具体功能前做点什么
 public class PreDecorator : BaseDecorator
{
    public PreDecorator(AbstractStudent student) : base(student)
    {
    }
    public override void Study()
    {
        Console.WriteLine("学习前看会儿小说");
        base.Study();
    }
}

//后缀装饰器,在调用具体功能后做点什么
public class NextDecorator : PreDecorator
{
    public NextDecorator(AbstractStudent student) : base(student)
    {
    }
    public override void Study()
    {
        base.Study();
        Console.WriteLine("学习辛苦啦,奖励自己一包辣条");
    }
}

//测试代码
public class DecoratorRunner : IRunner
{
    public void Run()
    {
        Console.WriteLine("没有用装饰器的基本功能:");
        var student = new Student();
        student.Study();
        Console.WriteLine();

        Console.WriteLine("使用前缀装饰器在基础功能之前做点什么");
        var preDecorator = new PreDecorator(student);
        preDecorator.Study();
        Console.WriteLine();

        Console.WriteLine("使用后缀装饰器在前缀装饰器功能之后做点什么");
        //注意:这里传入的前缀装饰器,在前缀装饰器的基础之上做扩展
        var nextDecorator = new NextDecorator(student);
        nextDecorator.Study();
    }
}

//输出:
//没有用装饰器的基本功能:
//我正在学习!!!
//
//使用前缀装饰器在基础功能之前做点什么
//学习前看会儿小说
//我正在学习!!!
//
//使用后缀装饰器在前缀装饰器功能之后做点什么
//学习前看会儿小说
//我正在学习!!!
//学习辛苦啦,奖励自己一包辣条 

可以看出,装饰器其实就是利用组合+继承(实现)+override不断包装和更新对象,使其功能得到扩展。装饰器是用于替换继承的设计模式,主要使用场景如下:

  • 想扩展实现类的功能,又不想添加太多子类
  • 需要动态增加和撤销功能(例如游戏技能)

装饰器的优点在于灵活,耦合性低,且不会改变现有结构。缺点则是嵌套过多会增加系统复杂度。

以上就是C#设计模式之适配器模式与装饰器模式的实现的详细内容,更多关于C#适配器模式 装饰器模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • C#装饰器模式(Decorator Pattern)实例教程

    本文以实例形式详细讲述了C#装饰器模式的实现方法.分享给大家供大家参考.具体实现方法如下: 现假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格.最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格. 每个产品都有名称和价格,首先设计一个关于产品的抽象基类. public abstract class ProductBase { public abstract string GetName(); public abstract double GetP

  • C# 设计模式系列教程-适配器模式

    1. 概述 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 解决的问题 即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 3. 模式中的角色 3.1 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可以是接口. 3.2 需要适配的类(Adaptee):需要适配的类或适配者类. 3.3 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接

  • c# 适配器模式

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

  • C#学习笔记之适配器模式详解

    什么是适配器模式? 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 什么时候运用适配器模式? 在想使用一个已经存在的类时,如果它的接口,也就是它的方法与我们当前的要求不相同时,就需要考虑用到适配器模式了. 一般而言,使用适配器模式是出于无奈之举,一般存在于软件开发后期或者维护期,在软件设计阶段,我们还是尽量避免该模式的使用. 适配器模式的组成   Target:目标接口,也就是客户所期待的接

  • 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

  • 解析C#设计模式编程中适配器模式的实现

    在实际的软件系统设计和开发中,为了完成某项工作需要购买一个第三方的库来加快开发.这带来一个问题,在应用程序中已经设计好的功能接口,与这个第三方提供的接口不一致.为了使得这些接口不兼容的类可以在一起工作,适配器模式提供了一种接口的适配机制. 适配器模式的设计思想在生活中经常会应用到,如我们在给手机充电的时候,不可能直接在220V电源上直接充电,而是用手机充电器转换成手机需要的电压才可以正常充电,否则就不可以完成充电,这个充电器就起到了适配的作用. 1.适配器模式简介 1.1.定义 适配器模式是通过

  • C#设计模式之适配器模式与装饰器模式的实现

    目录 结构型设计模式 适配器模式 实现代码 总结 装饰器模式 实现代码 结构型设计模式 创建型设计模式主要是为了解决创建对象的问题,而结构型设计模式则是为了解决已有对象的使用问题. 适配器模式 适配器模式比较好理解,因为在我们的日常生活中就很常见,如耳机转换线.充电器适配器.插座等,举个最常见的例子: 插座就是个适配器,将一个接口扩展为多个接口,将墙上的双孔接口转换为三孔接口.而这也就是适配器的作用:将一个接口转换为用户期望的另一个接口. 适配器的使用场景: 需要使用第三方SDK的核心功能,但其

  • PHP设计模式(八)装饰器模式Decorator实例详解【结构型】

    本文实例讲述了PHP设计模式:装饰器模式Decorator.分享给大家供大家参考,具体如下: 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类-这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的

  • PHP设计模式之装饰器模式定义与用法详解

    本文实例讲述了PHP设计模式之装饰器模式定义与用法.分享给大家供大家参考,具体如下: 什么是装饰器模式 作为一种结构型模式, 装饰器(Decorator)模式就是对一个已有结构增加"装饰". 适配器模式, 是为现在有结构增加的是一个适配器类,.将一个类的接口,转换成客户期望的另外一个接口.适配器让原本接口不兼容的类可以很好的合作. 装饰器模式是将一个对象包装起来以增强新的行为和责任.装饰器也称为包装器(类似于适配器) 有些设计设计模式包含一个抽象类,而且该抽象类还继承了另一个抽象类,这

  • 浅谈Java设计模式系列-装饰器模式

    一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是单方,和代理模式相同,而且目标必须是抽象的. 而实际上,装饰器模式和代理模式的实现方式基本一致,只在目标的存在上有些差别,这个后面我们具体讲述. 二.初步分析 上面提到了两点: 涉及的是单方 目标是抽象的 我们来想一下,所谓单方主要指的是在整个装饰器模式中不存在双方调用,要解决的也不是双方调用的问题,而是解决单方提供对外服务的问题,这个单方在自行对外提供服务时,功能不足,或

  • Java设计模式之装饰器模式

    本文由老王将建好的书房计划请小王来帮忙,小王却想谋权篡位,老王通过教育他引出装饰器设计模式,第二部分针对老王提出的建设性意见实现装饰器模式,第三部分针对装饰器模式在Jdk中的IO.Spring中的缓存管理器.Mybatis的运用来加强我们的理解,第四部分说明装饰器模式和代理模式的区别及他们各自的应用场景. 读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云,本地源码下载. 一.引出问题 上篇文章(Java设计模式之组合模式)对老王的书架改造以后,老王是相当的满意,看小王能力突出,

  • 深入解析设计模式中的装饰器模式在iOS应用开发中的实现

    装饰器模式可以在不修改代码的情况下灵活的为一对象添加行为和职责.当你要修改一个被其它类包含的类的行为时,它可以代替子类化方法. 一.基本实现 下面我把类的结构图向大家展示如下: 让我们简单分析一下上面的结构图,Component是定义一个对象接口,可以给这些对象动态地添加职责.ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责.Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需

  • PHP设计模式之装饰器模式实例详解

    本文实例讲述了PHP设计模式之装饰器模式.分享给大家供大家参考,具体如下: 装饰器模式又叫装饰者模式.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. UML类图: 角色: 组件对象的接口:可以给这些对象动态的添加职责 所有装饰器的父类:需要定义一个与组件接口一致的接口,并持有一个Component对象,该对象其实就是被装饰的对象. 具体的装饰器类:实现具体要向被装饰对象添加的功能.用来装饰具体的组件对象或者另外一个

  • PHP设计模式之装饰器模式定义与用法简单示例

    本文实例讲述了PHP设计模式之装饰器模式定义与用法.分享给大家供大家参考,具体如下: 装饰器模式: 如果已有对象的部分内容或功能性发生改变,但是不需要修改原始对象的结构或不使用继承,动态的扩展一个对象的功能,则应该使用装饰器模式. 简单点说:就是我们不应该去修改已有的类,而是通过创建另外一个装饰器类,通过这个装饰器类去动态的扩展其需要修改的内容,这样做的好处就是---- 1.我们可以保证类的层次不会因过多而发生混乱. 2.当我们需求的修改很小时,不用改变原有的数据结构. 代码引用自<PHP设计模

  • Java设计模式以虹猫蓝兔的故事讲解装饰器模式

    目录 什么是装饰器模式 优点 缺点 知识点 装饰器模式实现 七侠 虹猫 加料 加盐 加孜然 测试 总结 模式: 装饰器模式 案例: 黑小虎抓住了七侠,把虹猫烤了 什么是装饰器模式 装饰器(Decorator)模式的定义: 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式. 优点 1.装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用 2.通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效

  • python设计模式之装饰器模式

    目录 装饰器模式 python 装饰器语法糖 装饰器模式 装饰器模式解决什么问题? 增加新功能,且不改变原有功能和代码 选配,根据不同情况,动态调整功能 装饰器,顾名思义,就是用来装饰其他实物,增加被装饰物的功能而不改变被装饰物.这就像我们买车,同一款车型,有很多功能是选配的,但是车的核心功能不变.我们可以在购买时,根据需要选配不同的配置. 如何实现? 想象一下,你是一个装修工,如果要装饰一辆车,那么你首先需要有一辆车,而且在装饰过程中,你不能够改变车原有的功能(接口). 如类图所示: 核心功能

随机推荐