zoukankan      html  css  js  c++  java
  • 通俗易懂设计模式解析——装饰模式

    前言

      今天介绍的是结构型设计模式中的——装饰模式(Decorator Pattern),也是装饰器模式。装饰也就是装点修饰。例如我们对手机进行装饰,买了一个新的手机,先贴个钢化膜。在带一个壳。偶尔还在背面贴点贴纸。装一些挂件。这些等等行为也就是装饰。生活中的装饰是如此,那么编程中的装饰模式又是如何呢?

    装饰模式介绍

    一、来由

      在我们平常的软件系统中,经常会面临着向现有的对象添加一些新的功能或者新的职责,但是呢?又不能修改现有的类。以往常用的可能是继承来解决次问题。但是采用继承来说,随着扩展功能的增加,子类会变化的很膨胀。那么装饰器模式呢就解决这么一个问题,装饰器模式允许向一个现有的对象添加新的功能职责,同时又不改变其结构。将其功能职责划分。

    二、意图

      动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

    三、案例图

     

    四、装饰模式代码示例

    看上述案例图,装饰模式包含以下部分组成:

    抽象构件角色给出一个抽象接口,以规范准备接收新加的责任

    具体构件角色继承抽象构件角色,定义一个将要接收新加责任的类

    装饰角色继承抽象构件角色,包含一个构件角色对象的实例,并且实现抽象构件角色的接口

    具体装饰角色继承装饰角色,负责新加责任。

     

    我们继续看手机的案例,今天新买了一个手机,需要新加钢化膜,手机壳,然后才是一个我想要的手机。在这儿之后突然又想加一个挂件增加美感。我们看下如何使用装饰模式来实现手机装饰的问题吧:

    namespace Decorator_Pattern
    {
        class DecoratorPattern
        {
        }
        #region 抽象构件角色——抽象手机(抽象一个接口,准备接收新增的责任)=========
        /// <summary>
        /// 手机抽象类
        /// </summary>
        public abstract class Phone 
        {
            public abstract void Write();
        }
        #endregion
        #region 具体抽象构件角色——具体手机(实现抽象接口)===============================
        public class HuaweiV9Phone : Phone
        {
            public override void Write()
            {
                Console.WriteLine("对荣耀V9手机开始装饰");
            }
        }
        #endregion
        #region 装饰抽象角色——继承抽象构件角色,包含一个抽象构件角色对象的实例
       /// <summary>
       /// 装饰角色
       /// </summary>
        public abstract class Decorator : Phone 
        {
            public Phone _phone;
            protected Decorator(Phone phone)
            {
                this._phone = phone;
            }
            public override void Write()
            {
                if (_phone!=null)
                {
                    _phone.Write();
                }
            }
        }
        #endregion
        #region 具体装饰角色——手机加上钢化膜
        /// <summary>
        /// 具体装饰角色
        /// </summary>
        public class Membrane : Decorator
        { 
            public Membrane(Phone phone) : base(phone) { }
            public override void Write()
            {
                base.Write();
                AddMembrane();
            }
            public void AddMembrane() 
            {
                Console.WriteLine("手机加上了钢化膜!");
            }
        }
        #endregion
    
        #region 具体装饰角色——手机加上壳
        /// <summary>
        /// 具体装饰角色
        /// </summary>
        public class Shell : Decorator
        {
            public Shell(Phone phone) : base(phone) { }
            public override void Write()
            {
                base.Write();
                AddShell();
            }
            public void AddShell()
            {
                Console.WriteLine("手机加上了壳!");
            }
        }
        #endregion
    
        #region 具体装饰角色——手机挂件
        /// <summary>
        /// 具体装饰角色
        /// </summary>
        public class Pendant : Decorator
        {
            public Pendant(Phone phone) : base(phone) { }
            public override void Write()
            {
                base.Write();
                AddPendant();
            }
            public void AddPendant()
            {
                Console.WriteLine("手机加上了挂件!");
            }
        }
        #endregion
    }
        class Program
        {
            static void Main(string[] args)
            {
                //现在获得了一个手机
                Phone phone = new HuaweiV9Phone();
    
                //裸机一个,先贴个膜
                Decorator membrane = new Membrane(phone);
                membrane.Write();
                Console.WriteLine();
    
                //还是觉得不顺眼,再加个外壳看看
                Decorator membraneShell = new Shell(membrane);
                //现在我同时有钢化膜和外壳了
                membraneShell.Write();
                Console.WriteLine( );
    
                //这时候我觉得还是不要外壳了。我需要同时又钢化膜和手机挂件
                Decorator membranePendant = new Pendant(membrane);
                membranePendant.Write();
                Console.WriteLine();
    
    
                Console.ReadLine();
            }
        }

    使用场景及优缺点

    一、使用场景

    1、需要扩展类的功能或者为类增加新增的责任

    2、需要动态增加功能或者撤销功能

    二、优点

    1、装饰类与被装饰类可以独立发展,不会互相耦合, 极易扩展、符合开闭原则

    2、装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。

    三、缺点

    1、增加系统复杂度,更加易于出错,难于排查错误。增大了学习与理解的难度。

    总结

      装饰模式到这里就短暂的介绍完了。在平常中,装饰模式使用的情况较多。一般来说,我们扩展一个类经常选择继承的方式,但是由于继承是为类引入静态的特征。并且随着功能增加的越来越多,子类会越来越膨胀。装饰模式是可以替代继承方式的。前面结构型的设计模式也学习了适配器模式与桥接模式。再加上今天学习的装饰模式。我们都需要细细分析其区别及使用场景,以便于后期使用时不至于混淆其用法。要用的恰到好处。

    只有经历过地狱般的折磨,才有征服天堂的力量。只有流过血的手指才能弹出世间的绝唱。

        C#设计模式系列目录

    欢迎大家扫描下方二维码,和我一起踏上设计模式的闯关之路吧!

      

  • 相关阅读:
    flutter doctor出现问题 [!] Android toolchain
    CSS中的cursor属性
    致蝙蝠侠阿卡姆三部曲——最伟大的改编游戏
    ajax的使用:例题、ajax的数据处理
    用ajax对数据进行删除和查看
    ThinkPhp框架:验证码功能
    ThinkPhp框架:父类及表单验证
    ThinkPhp框架:分页查询和补充框架知识
    ThinkPhp框架对“数据库”的基本操作
    ThinkPHP框架知识的注意点
  • 原文地址:https://www.cnblogs.com/hulizhong/p/11454474.html
Copyright © 2011-2022 走看看