• 装饰者模式


    1. 引言

    在软件系统中如果通过继承来扩展对象的功能,但是由于继承是静态特质,使得这种扩展缺乏灵活性。在软件开发时,需要开发一个组件,其组件由其他零件构成,比如装修,美化手机等等。如果利用继承的话,就可能生成很多子类,比如西式装修子类、杭州风格装修子类等等,为了解决这个问题,提供了装饰者模式动态给对象添加额外的职责。
    定义:以对客户透明的方式对对象动态添加额外的责任,装饰者模式相比生成子类可以更灵活的增加功能。
    例子如:不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
    画框装饰者模式(引用他人)

    2.原版设计

    • 2.1组件成品

      日志组件
      设计一个写日志组件,框架如上图,提供两个具体类分别写消息日志、异常日志。

    • 2.2功能优化
      在原版基础上日志信息的错误严重级别功能和记录日志信息时间的功能。
      利用继承完成,结构图如下:
      改进版
      如果需要相应的功能,直接使用这些子类就可以了。这里我们采用了类的继承方式来解决了对象功能的扩展问题,这种方式是可以达到我们预期的目的。然而,它却带来了一系列的问题。随着以后扩展功能的增多,子类会迅速的膨胀,可以看到,子类的出现之前两个子类与新增加的接口的一种排列组合关系,所以类结构会变得很复杂而难以维护。记住肯定不能对MessageLog以及ExceptionLog进行修改,禁止修改代码

    • -

    3.装饰者模式

    针对上述问题,装饰者模式提供一个解决方案。框图设计如下:

    这里写图片描述

    public abstract class Log
    {
        public abstract void WriteLog();
    
    }
    
    public class MessageLog : Log
    {
        public override void WriteLog()
        {
           //实现消息日志记录
            throw new System.NotImplementedException();
        }
    
    }
    
    public class ExceptionLog : Log
    {
        public override void WriteLog()
        {
            //实现异常消息记录
            throw new System.NotImplementedException();
        }
    
    }
    改进的代码
    
    //抽象的新增日志类。
    public class ExceptionLog : Log
    {
        public override void WriteLog()
        {
            //实现异常消息记录
            throw new System.NotImplementedException();
        }
    
    }
    //继承的具体实施子类
    public class AdvMessageLog : RecordLog
    {
        //必须需要传进基类Log,这样才能进行装饰
        //协商Base(log)后,这样RecordLog中Log对象才能赋值,后续的base调用才可以用
        public AdvMessageLog(Log log)
            : base(log)
        {
        }
        public virtual void RecordTime()
        {
            throw new System.NotImplementedException();
        }
    
        public virtual void SetPriority()
        {
            throw new System.NotImplementedException();
        }
    
        public override void WriteLog()
        {
            base.WriteLog();
            //此处就是添加的新的行为
            SetPriority();
        }
    
    }
    //客户端调用
    class Cuetomer
    {
        static void main(string [] args)
        {
            //声明一个日志对象
            Log _log = new MessageLog();
            //要求日志对象写上时间
            RecordLog _timeLog = new AdvMessageLog(_log);
            _timeLog.WriteLog();
            //这样就完成调用了,很简单吧
        }
    }
    View Code
    • 在装饰者模式中各个角色有:
      *抽象构件(Log)角色:给出一个抽象接口,以规范准备接受附加责任的对象。
      具体构件(MessageLog)角色:定义一个将要接收附加责任的类。
      装饰(RecordLog)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
      具体装饰(AdvmessageLog和AdvExceptionLog)角色:负责给构件对象 ”贴上“附加的责任。*

    4.综述

    组件(Component类)在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明,换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

    • 装饰者模式的优缺点

    优点:
    装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活,使用很少的类。
    通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合,利用组合原则,很好的改善效果。
    装饰者模式有很好地可扩展性
    缺点:装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。并且更多的对象会是的差错变得困难,特别是这些对象看上去都很像。

    • 适用性

    在以下情况下应当使用装饰模式:
    1.需要扩展一个类的功能,或给一个类增加附加责任。
    2.需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
    3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Math 和 Date
    GRID布局
    移动端项目布局类型
    媒体查询 + rem用法
    字符串
    ES5 中常见的数组常用方法
    数组的排序
    毕设制作:前端界面 2020-02-01
    阅读笔记十六——排序算法
    阅读笔记十五——阿里面试题
  • 原文地址:https://www.cnblogs.com/polly333/p/4705678.html
Copyright © 2020-2023  润新知