设计模式学习-装饰模式

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

  (虚拟场景)这不,老大刚过来说,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();
这样,我们比较好的实现了对修改的关闭,对扩展的开放,以后再增加比如打开短消息,通知原用户的功能等也没有问题了
posted @ 2012-06-05 11:29  kdalan  阅读(703)  评论(0编辑  收藏  举报