zoukankan      html  css  js  c++  java
  • 设计模式学习-装饰模式

      维护系统,需求变更是程序猿心中永远的痛...

      (虚拟场景)这不,老大刚过来说,XX,你需要把XX系统的站内短信息系统修改一下,接收人打开后,修改短信息状态为已读。

      我:“好的,没问题,这就改。”

      先看看之前的代码,恩,貌似很简单,直接操作数据库修改状态好了。 

    View Code 
        public class MessageManage 
        {
            public string GetMessage() 
            {
                return "短消息XXXXXXXXXX";
            }
        }

        public class Client 
        {
            static void Main() 
            {
                MessageManage msgManage = new MessageManage();
                Console.WriteLine(msgManage.GetMessage());
            }

      修改后的代码:

    View Code 
        public class MessageManage 
        {
            public string GetMessage() 
            {
                return "短消息XXXXXXXXXX";
            }

            public void ChangeStatus() 
            {
                Console.WriteLine("短消息状态修改");
            }
        }

        public class Client 
        {
            static void Main() 
            {
                MessageManage msgManage = new MessageManage();
                msgManage.ChangeStatus();
                Console.WriteLine(msgManage.GetMessage());
            }

      代码测试完,提交了,老大忽然又跑来说,那啥,我刚忘记了,查看完短消息后要保存操作日志到TXT文档里。 

      我心里说:"这些需求早点怎么不提,应该是设计阶段要解决的,乱码三千字...省略...."。没办法,有需求就要改,拿人钱财,替人消灾。
      作为一个有思想的,想进步的猴子,我觉得我不能一而再,再尔三的违反开闭原则。趁现在短消息系统还比较简单,我决定重构短消息这块的代码。功能需求不断增加,用个什么设计模式好呢?记得有一个动态的给对象增加功能的模式。

    模式概述: 

    Decorator Pattern,又叫装饰模式、装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

    UML类图:


    其中类与对象之间的关系为:

    • Component类
      定义装饰对象与被装饰对象的共同的装饰行为

    • ConcreateComponent类
      被装饰的对象

    • Decorator类
      装饰类的抽象类,包含了Component类的实例(表明将来的具体装饰类都有一个明确的装饰对象)并实现Component类中装饰对象和被装饰对象的共同行为,

    • ConcreteDecorator类 
      具体的装饰类,实现了Decorator类

     现在,我们就按装饰模式重构一下我们的代码:

    View Code 
        public abstract class Component 
        {
            public abstract string GetMessage();
        }

        public class MessageManage : Component 
        {
            public override string GetMessage()
            {
                return "短消息XXXXXXXXXX";
            }
        }

        public abstract class Decorator : Component 
        {
            private Component _com;

            public Decorator(Component com) 
            {
                this._com = com;
            }

            public override string GetMessage()
            {
                return _com.GetMessage();
            }
        }

        public class ConcreteDecoratorA : Decorator 
        {
            public ConcreteDecoratorA(Component com)
                : base(com)
            {
            }

            private void changeStatus() 
            {
                Console.WriteLine("短消息状态修改");
            }

            public override string GetMessage()
            {
                this.changeStatus();
                return base.GetMessage();
            }
    客户端调用:
    View Code 
            static void Main()
            {
                MessageManage msg = new MessageManage();
                ConcreteDecoratorA actionA = new ConcreteDecoratorA(msg);
                Console.WriteLine(actionA.GetMessage());
                Console.ReadLine();
    现在我们增加保存日志到Txt的功能,原代码不需要修改,新增代码如下:
    View Code 
        public class ConcreteDecoratorB : Decorator
        {
            public ConcreteDecoratorB(Component com)
                : base(com)
            {
            }

            private void writeLog()
            {
                Console.WriteLine("保存操作日志到Txt文件");
            }

            public override string GetMessage()
            {
                this.writeLog();
                return base.GetMessage();
            }
    客户端代码变为:
    View Code 
            static void Main()
            {
                MessageManage msg = new MessageManage();
                ConcreteDecoratorA actionA = new ConcreteDecoratorA(msg);
                ConcreteDecoratorB actionB = new ConcreteDecoratorB(actionA);
                Console.WriteLine(actionB.GetMessage());
                Console.ReadLine();
    这样,我们比较好的实现了对修改的关闭,对扩展的开放,以后再增加比如打开短消息,通知原用户的功能等也没有问题了
  • 相关阅读:
    elasticsearch 不能通过9200端口访问
    elasticsearch 2.0+ 安装 Marvel
    修改es最大返回结果数
    ElasticSearch的Marvel更新license
    python-execjs(调用js)
    爬取豆瓣电影排名的代码以及思路
    docker的安装
    mysql主从同步
    Docker配置yapi接口
    第24课
  • 原文地址:https://www.cnblogs.com/kdalan/p/2536241.html
Copyright © 2011-2022 走看看