设计模式09: Decorator 装饰模式(结构型模式)

Decorator 装饰模式(结构型模式)

子类复子类,子类何其多
加入我们需要为游戏中开发一种坦克,除了不同型号的坦克外,我们还希望在不同场合中为其增加以下一种多种功能:比如红外线夜视功能,比如水路两栖功能,比如卫星定位功能等等。

问题代码:

    /// <summary>
    /// 抽象坦克
    /// </summary>
    public abstract class Tank
    {
        public abstract void Shot();
        public abstract void Run();
    }
    //各种型号
    public class T50 : Tank
    {
        public override void Shot()
        {
            //...
        }

        public override void Run()
        {
            //...
        }
    }

    public class T75 : Tank
    {
        public override void Shot()
        {
            //...
        }

        public override void Run()
        {
            //...
        }
    }
    /// <summary>
    /// 红外线夜视
    /// </summary>
    public interface IA
    {
        //...
    }
    /// <summary>
    /// 水陆两栖
    /// </summary>
    public interface IB
    {
        //...
    }
    //各种不同功能组合
    public class T50A : T50, IA
    {
        //...
    }

    public class T50B : T50, IB
    {
        //...
    }

    public class T50AB : T50,IA,IB
    {
        //...
    }

动机(Motivation)
上述描述的问题根源在于我们“过度的使用继承来扩展对象的功能”,由于继承为类引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。

如何使“对象功能的扩展”能够根据需求来动态地(运行时)实现?同时避免“扩展功能增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低?

意图(Intent)

动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。——《实际模式》GoF

实例代码:

    /// <summary>
    /// 抽象坦克
    /// </summary>
    public abstract class Tank
    {
        public abstract void Shot();
        public abstract void Run();
    }
   //各种型号
    public class T50 : Tank
    {
        public override void Shot()
        {
            //...
        }

        public override void Run()
        {
            //...
        }
    }

    public class T75 : Tank
    {
        public override void Shot()
        {
            //...
        }

        public override void Run()
        {
            //...
        }
    }
    public abstract class Decorator : Tank//接口继承,抽象类可以看做接口
    {
        private Tank tank;//Has-A对象组合

        public Decorator(Tank tank)
        {
            this.tank = tank;
        }

        public override void Shot()
        {
            tank.Shot();
        }

        public override void Run()
        {
            tank.Run();
        }
    }
    /// <summary>
    /// 红外功能扩展
    /// </summary>
    public class DecoratorA : Decorator
    {
        public DecoratorA(Tank tank):base(tank)
        {
        }
        public override void Shot()
        {
            //红外功能扩展
            //do shot...
            base.Shot();
        }

        public override void Run()
        {
            //红外功能扩展
            //do run...
            base.Run();
        }
    }
    /// <summary>
    /// 水陆两栖功能扩展
    /// </summary>
    public class DecoratorB : Decorator
    {
        public DecoratorB(Tank tank):base(tank)
        {
        }
        public override void Shot()
        {
            //水陆两栖功能扩展
            //do shot...
            base.Shot();
        }

        public override void Run()
        {
            //水陆两栖功能扩展
            //do run...
            base.Run();
        }
    }
    class App
    {
        public static void Main()
        {
            Tank tank=new T50();
            DecoratorA da = new DecoratorA(tank);//红外功能扩展
            DecoratorB db = new DecoratorB(da);//红外、水陆两栖功能扩展
        }
    }

Decorator模式的几个要点

  • 通过采用组合,而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。
  • Tank类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Tank类应该是透明——换言之Tank类无需知道Decorator,Decorator类是从外部来扩展Tank类的功能。
  • Decorator类在接口上表现为is-a Tank类的继承关系,即Decorator继承了Tank类所具有的接口。在实现上又表现为has-a Tank的组合关系,即Decorator类又使用了另一个Tank类。我们可以使用一个或者多个Decorator对象来“装饰”一个Tank对象,而且装饰后的对象仍然是Tank对象。
  • Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。
时间: 2024-11-10 08:12:00

设计模式09: Decorator 装饰模式(结构型模式)的相关文章

设计模式之7个结构型模式

结构型模式概述 结构型模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的.功能更为强大的结构. 结构型模式概述结构型模式可以分为类结构型模式和对象结构型模式 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系. 对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法.根据"合成复用原则",在系统中

《大话设计模式》笔记(2)——结构型模式

7.适配器模式(Adapter) 定义:有时候也称包装样式或者包装,将一个类的接口适配成用户所期待的.它使得原本接口不兼容而不能一起工作的类可以一起工作. UML: PS:适配器模式算比较容易理解的,其实现主要是在适配器Adapter包装一个Adaptee,并向外部提供客户所需要规格的接口,而其该接口的实现就是调用源接口Adaptee.SpecificRequest(). 适配器模式是因为目标接口和源接口规格不匹配而设计的模式. 应用场景:.net中的DataAdapter就是DataSet与数

NET设计模式 第三部分 结构型模式(7):适配器模式(Adapter Pattern)

适配器模式(Adapter Pattern) ——.NET设计模式系列之八 Terrylee,2006年2月 概述 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的.那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?这就是本文要说的Adapter 模式. 意图 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可

设计模式-07 适配器模式(结构型模式)

一  适配器模式 是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 主要解决: 主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的. 关键代码:适配器继承或依赖已有的对象,实现想要的目标接口. 使用场景: 需要在现有系统中调用第三方提供的服务,比如阿里云服务,过一段时间后调用另外一个云服务商提供的服务,比如华为云. 美国电器 110V,中国

结构型模式:代理模式

文章首发: 结构型模式:代理模式 七大结构型模式之七:代理模式. 简介 姓名 :代理模式 英文名 :Proxy Pattern 价值观 :为生活加点料 个人介绍 : Provide a surrogate or placeholder for another object to control access to it. 为其他对象提供一种代理以控制对这个对象的访问. (来自<设计模式之禅>) 你要的故事 咱们从事 IT 行业,随时都可能上网查东西,如果网络速度慢或者网络访问受限制,那是相当的

设计模式(八) : 结构型模式--装饰模式

装饰模式的目的是为了给一个对象动态的增加一些功能.装饰对象和被装饰的对象实现同一个接口,装饰对象持有被装饰对象的实例. 类图: 示意性代码: package com.javadesignpattern.Decorator; public interface Component { void sampleOperation(); } package com.javadesignpattern.Decorator; public class ConcreteComponent implements

设计模式(十):Decorator装饰者模式 -- 结构型模式

1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者

设计模式(八)装饰器模式Decorator(结构型)

设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许

设计模式-10 装饰模式(结构型模式)

一 装饰模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 主要解决:扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀. 关键代码:1.Component 类充当抽象角色,不应该具体实现. 2.修饰类引用和继承 Component 类,具