• 重看Decorator Pattern,联想到Delegate传递及Flags Enum--欢迎拍砖!


      话说装饰模式(Decorator)的动机是“动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。[GOF 《设计模式》]”。再次学到该模式,有感,联想到Delegate和Flags Enum。Delegate也可实现在已有功能上动态添加新功能,有点”装饰“的意图,Flags Enum可以进行组合使用。如果对装饰模式不熟悉,请移步大神博文http://terrylee.cnblogs.com/archive/2006/03/01/340592.html。本文描述该模式的相关思考,不正之处,请大神指点拍砖!谢谢

      该模式的UML图: ,Decorator抽象,既继承Component又组合引用Component,为什么需要这样呢?从该模式的具体代码看到,装饰之上可以继续装饰,故需要引用一个装饰,为什么有需要继承呢,感觉装饰需要一个抽象吧。

      现在来假设一个场景,有一个现有的对象,如下:

    public class Component
        {
            public void Operation(string msg)
            {
                Console.WriteLine("Compent.Operation。hi,:"+msg);
            }
        }

     该操作不是可override的,那怎么使用装饰模式来扩展新功能呢?这里给出装饰模式的“变形代码”

        public class ComponentWrapper
        {
            public virtual void Operation(string msg)
            {
                Component m_Component = new Component();
                m_Component.Operation(msg);
            }
        }
    
        public class ComponentWrapper1 : ComponentWrapper
        {
            private ComponentWrapper m_decorator;
            public ComponentWrapper1(ComponentWrapper decorator)
            {
                m_decorator = decorator;
            }
            public override void Operation(string msg)
            {
                m_decorator.Operation(msg);
                Add(msg);
            }
            public static void Add(string msg)
            {
                Console.WriteLine("ComponentWrapper1 added");
            }
        }
    
        public class ComponentWrapper2 : ComponentWrapper
        {
            private ComponentWrapper m_decorator;
            public ComponentWrapper2(ComponentWrapper decorator)
            {
                m_decorator = decorator;
            }
            public override void Operation(string msg)
            {
                m_decorator.Operation(msg);
                Add(msg);
            }
            public static void Add(string msg)
            {
                Console.WriteLine("ComponentWrapper2 added");
            }
        }
    //调用代码            
    ComponentWrapper d = new ComponentWrapper();//未装饰 ComponentWrapper d1 = new ComponentWrapper1(d);//装饰上功能1 ComponentWrapper d2 = new ComponentWrapper2(d1);//装饰上功能2 d2.Operation("stevey");

    上面代码中,ComponentWrapper 作为装饰的基类,对已有功能进行包装,在装饰1中继承装饰基类又包含一个装饰。可能说包装感觉更形象一点,一层一层的包装,或者说人穿的衣服也是一层一层的,哈哈。可以看到,一个装饰对象就作为一个”功能集“整体,实际上是一个引用装饰链,调用依次传递到顶端。由此联想到,功能也可以追加,功能也可以做成像链式依次执传递。遵循上面场景的方法契约,于是就凭着感觉写出如下code:

        public static class ComponentExtension
        {
            /// <summary>
            /// 在已有操作之后加上新操作
            /// </summary>
            /// <param name="action">原操作</param>
            /// <param name="otherAction">新操作</param>
            /// <returns></returns>
            public static Action<string> After(this Action<string> action,Action<string> otherAction)
            {
                return (msg) => {
                    action(msg);
                    otherAction(msg);
                };
            }
    
            public static Action<string> Before(this Action<string> action, Action<string> otherAction)
            {
                return (msg) =>
                {
                    otherAction(msg);
                    action(msg);
                };
            }
        }

    调用代码:

    //使用delegate装饰新功能
                Action<string> action = new Component().Operation;
                Action<string> wrapper1 = action.After(ComponentWrapper1.Add);//装饰上功能1
                Action<string> wrapper2 = wrapper1.After((msg) =>//装饰上功能2
                {
                    Console.WriteLine("wrapper2 added");
                });
                wrapper2("hello");
                Console.WriteLine("*****************************");
                //
                Action<string> wrapper3 = wrapper1.After(wrapper2);
                wrapper3("(原功能+功能1)+{(原功能+功能1)+装饰上功能2}");//在已有的装饰整体上加上另一个装饰

    上面的代码可以链式,其他不解释了,代码是最直接的意思表达,在一个功能上继续包装一个功能,得到的就是一个装饰,可以作为整体,继续装饰。。。貌似比模式轻量级点不。

      标记枚举,也有点”装饰“的味道,MSDN上的代码:

    [Flags]
        enum Days2
        {
            None = 0x0,
            Sunday = 0x1,
            Monday = 0x2,
            Tuesday = 0x4,
            Wednesday = 0x8,
            Thursday = 0x10,
            Friday = 0x20,
            Saturday = 0x40
        }
    //Flags Enum
                // Initialize with two flags using bitwise OR.
                var meetingDays = Days2.Tuesday | Days2.Thursday;
    
                // Set an additional flag using bitwise OR.
                meetingDays = meetingDays | Days2.Friday;
    
                Console.WriteLine("Meeting days are {0}", meetingDays);
                // Output: Meeting days are Tuesday, Thursday, Friday
    
                // Remove a flag using bitwise XOR.
                meetingDays = meetingDays ^ Days2.Tuesday;
                Console.WriteLine("Meeting days are {0}", meetingDays);
                // Output: Meeting days are Thursday, Friday

      就写到这里吧,感觉有点语无伦次,不在状态,大家就将就看吧。算是一点装饰模式的读后感,欢迎大家讨论,不正之处,还请指出,谢谢!

  • 相关阅读:
    bootstrap-图片样式记录
    关于json数据中的多反斜杆转译--StringEscapeUtils.unescapeJava(踩过的坑)
    Nginx与tomcat组合的简单使用
    多进程之间的互斥信号量的实现(Linux和windows跨平台)
    跨平台(win和unix)的线程封装类
    linux 静态库、共享库
    WinMain与wWinMain,win32的字符集问题
    linux下添加动态链接库路径、动态库加载等方法
    win系统动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)
    dll程序开发总结
  • 原文地址:https://www.cnblogs.com/skysoft001/p/3451801.html
Copyright © 2020-2023  润新知