千家信息网

C#适配器模式与装饰器模式如何实现

发表于:2024-10-28 作者:千家信息网编辑
千家信息网最后更新 2024年10月28日,本篇内容介绍了"C#适配器模式与装饰器模式如何实现"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!结构
千家信息网最后更新 2024年10月28日C#适配器模式与装饰器模式如何实现

本篇内容介绍了"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#适配器模式与装饰器模式如何实现"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

适配 适配器 功能 模式 接口 电压 学习 基础 前缀 组合 系统 代码 得了 情况 方式 正在 结构 设计模式 设计 原则 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 消防工程需要网络技术 值得信任的分布式数据库事务 北京公安大学网络安全与执法 软件开发企业的设计费用 为什么最近要加强网络安全 网络安全主题班会教案中学 分众传媒软件开发 数据库还原 正在使用 谢谢网络安全的第一个时代 鞍山java软件开发 软件开发工作内容及职能 软件开发为什么要用到框架 软件开发类创业公司 个人笔记本架设服务器 rpc服务器怎么做便宜 浙江无极互联网科技公司电话 福建企业软件开发要多少钱 辽宁app软件开发价钱 数据库中科学计数法 网络安全工作岗位简绍 惠尔顿网络安全审计系统10设置 网络安全法规定 谁负责统筹 财务数据库管理系统数据 台州越界网络技术有限公司 it软件开发工作室图片大全 网络安全漏洞处罚 能买lol服务器装家里吗 上海交通大学网络安全博士怎样 国家永久农田数据库 黄浦区推广软件开发供应商家
0