• 设计模式学习笔记装饰模式


    装饰模式:(Decorator),动态地给一个对象添加一些额外的职责,比单纯的继承更为灵活合理,应用场合比如java的System.IO各种输出就是通过装饰模式来实现的,还有一些日志类,动态的添加日志记录的功能,将耦合度降到最低。这里的基本内容参照大话设计模式的,但是这一节将的并不好,再额外做些补充,供自己和园友们做备忘录用。

          Componet 是定义一个对象接口,可以给这些对象动态的添加职责,

          ConcreteComponent是定义了一个具体的对象, 也可以给这些对象添加一些职责。

          Decorator,装饰抽象类,继承了Component,从外类来扩展Component的功能,

          但对于Component来说,是无需要知道Decorator类的存在。

          至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能

    UML画的不熟练,错误地方望大家指出

    1.定义抽象接口

        abstract class Component
    {
    public abstract void Operation();
    }

    2.定义一个基础的实现类

        class ConcreteComponent:Component
    {
    public override void Operation()
    {
    Console.WriteLine(
    "具体的对象操作");
    }
    }

    3.定义装饰调度类

       abstract class Decorator:Component
    {
    protected Component component;

    /// <summary>
    /// 设置定义的接口
    /// </summary>
    /// <param name="component"></param>
    public void SetComponent(Component component)
    {
    this.component = component;
    }
    /// <summary>
    /// 重写Operation,实际上执行的是Component的Operation()
    /// </summary>
    public override void Operation()
    {
    if(component!=null)
    {
    component.Operation();
    }
    }
    }

    4.定义具体装饰类A

        class ConcreteDecoratorA:Decorator
    {
    /// <summary>
    /// 当前类的私有属性,区别于其他类
    /// </summary>
    private void AddBehavior()
    {
    Console.WriteLine(
    "CocreteDecoratorA 的私有方法");
    }

    public override void Operation()
    {
    /*首先运行了原Component的Operation()
    再执行了当前类的功能,相当于对原Component进行了装饰
    */
    AddBehavior();
    Console.WriteLine(
    "具体装饰对象A的操作");
    base.Operation();
    }
    }

    5.定义具体装饰类B

        class ConcreteDecoratorB : Decorator
    {
    /// <summary>
    /// 当前类的私有方法,区别于其他类
    /// </summary>
    private void AddBehavior()
    {
    Console.WriteLine(
    "具体对象B的装饰");
    }

    public override void Operation()
    {
    /*首先运行了原Component的Operation()
    再执行了当前类的功能,相当于对原Component进行了装饰
    */

    AddBehavior();
    Console.WriteLine(
    "具体装饰对象B的操作");
    base.Operation();
    }
    }

    客户端调用:

            /// <summary>
    /// 装饰模式
    /// </summary>
    static void TestDecorator()
    {
    //装饰的方法:首先用ConcreteComponent实例化对象c
    ConcreteComponent c = new ConcreteComponent();

    ConcreteDecoratorA cdA
    = new ConcreteDecoratorA();
    ConcreteDecoratorB cdB
    = new ConcreteDecoratorB();

    //然后用ConcreteDecoratorA 的实例化对象cdA来包装c
    cdA.SetComponent(c);
    //再用ConcreteDecoratorB的实例化对象cdB来包装cdA
    cdB.SetComponent(cdA);
    //最终执行cdB的Operation()
    cdB.Operation();

    Console.Read();
    }

      

    小结:装饰类的功能很强大,但是灵活运用起来不简单,需要仔细体会面向对象的设计,以下是贴出在网上搜集的一个比较好的例子,比大话设计模式的里面 的那个例子更严谨。

    View Code
    namespace DesignPatternLab.DecoratoryPackage
    {
    /// <summary>
    /// 首先,我们需要一个手机的接口或者是抽象类,我这里就用抽象类来实现,代码如下
    /// </summary>
    public abstract class AbstractCellPhone
    {
    public abstract string CallNumber();
    public abstract string SendMessage();
    }
    //然后,我再来实现Nokia和Moto的手机类
    public class NokiaPhone : AbstractCellPhone
    {
    public override string CallNumber()
    {
    return "NokiaPhone call sombody";
    }

    public override string SendMessage()
    {
    return "NokiaPhone send a message to somebody";
    }
    }
    //然后,我再来实现Nokia和Moto的手机类
    public class MotoPhone : AbstractCellPhone
    {
    public override string CallNumber()
    {
    return "MotoPhone call sombody";
    }

    public override string SendMessage()
    {
    return "MotoPhone send a message to somebody";
    }
    }
    //接下来我需要一个Decorator接口或者抽象类,实现代码如下
    public abstract class CellDecorator : AbstractCellPhone
    {
    AbstractCellPhone _phone;

    public CellDecorator(AbstractCellPhone phone)
    {
    _phone
    = phone;
    }

    public override string CallNumber()
    {
    return _phone.CallNumber();
    }

    public override string SendMessage()
    {
    return _phone.SendMessage();
    }
    }

    /// <summary>
    /// 这个Decorator即继承了AbstractCellPhone,
    /// 又包含了一个私有的AbstractCellPhone的对象。
    /// 这样做的意义是:Decorator类又使用了另外一个Component类。
    /// 我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,
    /// 且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,
    /// 它们要继承自Decorator,代码如下
    /// </summary>
    public class DecoratorGPS : CellDecorator
    {
    public DecoratorGPS(AbstractCellPhone phone):base(phone)
    { }

    public override string CallNumber()
    {
    return base.CallNumber() + " with GPS";
    }

    public override string SendMessage()
    {
    return base.SendMessage() + " with GPS";
    }
    }

    public class DecoratorBlueTooth : CellDecorator
    {
    public DecoratorBlueTooth(AbstractCellPhone phone)
    :
    base(phone)
    { }

    public override string CallNumber()
    {
    return base.CallNumber() + " with BlueTooth";
    }

    public override string SendMessage()
    {
    return base.SendMessage() + " with BlueTooth";
    }
    }
    }

    客户端调用:

            /// <summary>
    /// 装饰模式案例
    /// </summary>
    static void TestDecoratorCellPhone()
    {
    AbstractCellPhone phone
    = new NokiaPhone();
    Console.WriteLine(phone.CallNumber());
    Console.WriteLine(phone.SendMessage());
    DecoratorGPS gps
    = new DecoratorGPS(phone); //add GSP
    Console.WriteLine(gps.CallNumber());
    Console.WriteLine(gps.SendMessage());
    DecoratorBlueTooth bluetooth
    = new DecoratorBlueTooth(gps); //add GSP and bluetooth
    Console.WriteLine(bluetooth.CallNumber());
    Console.WriteLine(bluetooth.SendMessage());
    Console.Read();
    }
  • 相关阅读:
    61序列化二叉树
    60把二叉树打印成多行
    59按之字形顺序打印二叉树
    58对称的二叉树
    57二叉树的下一个结点
    56删除链表中重复的结点
    55链表中环的入口结点
    Python100天打卡-Day10
    Python100天打卡
    点至直线的距离和垂足点计算
  • 原文地址:https://www.cnblogs.com/jqbird/p/2142734.html
Copyright © 2020-2023  润新知