穿什么有这么重要吗?————装饰模式

来源:互联网 发布:java web nodejs web 编辑:程序博客网 时间:2024/06/08 09:15

1、自己C++实现的

 

 

2、网上抄的

Decorator装饰模式是一种结构型模式,它主要是解决:“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。继承为类型引入的静态特质的意思是说以继承的方式使某一类型要获得功能是在编译时。所谓静态,是指在编译时;动态,是指在运行时。

GoF《设计模式》中说道:动态的给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。

下面来看看Decorator模式的结构:



看这个结构好像不是很明白,下面我根据代码讲解一下这个结构。我想了一个场景:我们现在用的手机功能很多,我就用Decorator模式实现一下对某个手机的GSP和蓝牙功能扩展。

首先,我们需要一个手机的接口或者是抽象类,我这里就用抽象类来实现,代码如下:

public abstract class AbstractCellPhone

    {

        public abstract string CallNumber();

        public abstract string SendMessage();

}

AbstractCellPhone也就是结构图中的Component,然后,我再来实现NokiaMoto的手机类,这类要继承AbstractCellPhone,也就是图中ConcreteComponent类要继承Component,实现代码如下:

public class NokiaPhone : AbstractCellPhone

    {

        public override string CallNumber()

        {

            return "NokiaPhone call sombody";

        }

 

        public override string SendMessage()

        {

            return "NokiaPhone send a message to somebody";

        }

    }

 

    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 Decorator:AbstractCellPhone

    {

        AbstractCellPhone _phone;

 

        public Decorator(AbstractCellPhone phone)

        {

            _phone = phone;

        }

 

        public override string CallNumber()

        {

            return _phone.CallNumber();

        }

 

        public override string SendMessage()

        {

            return _phone.SendMessage();

        }

  }

正如结构图中,这个Decorator即继承了AbstractCellPhone,又包含了一个私有的AbstractCellPhone的对象。这样做的意义是:Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,它们要继承自Decorator,代码如下:

public class DecoratorGPS : Decorator

    {

        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 : Decorator

    {

        public DecoratorBlueTooth(AbstractCellPhone phone)

            : base(phone)

        { }

 

        public override string CallNumber()

        {

            return base.CallNumber() + " with BlueTooth";

        }

 

        public override string SendMessage()

        {

            return base.SendMessage() + " with BlueTooth";

        }

 }

最后,用客户端程序验证一下:

static void Main(string[] args)

        {

             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();

     }

执行结果:

NokiaPhone call sombody

NokiaPhone send a message to somebody

NokiaPhone call sombody with GPS

NokiaPhone send a message to somebody with GPS

NokiaPhone call sombody with GPS with BlueTooth

NokiaPhone send a message to somebody with GPS with BlueTooth

 

从执行的结果不难看出扩展功能已被添加。最后再说说Decorator装饰模式的几点要点:

1、通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。

2Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明——换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

3Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。(在这里我想谈一下我的理解:当我们实例化一个Component对象后,要给这个对象扩展功能,这时我们把这个Component对象当作参数传给Decorator的子类的构造函数——也就是扩展方法的功能类。对于引用类型传参时,实际上只是传递对象的地址,这样,在功能扩展是,操作的应该是同一个对象)

4Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。Decorator是在运行时对功能进行组合。

 

 

 

 

3、还是网上找的

装饰(Decorator)模式又名包装器(Wrapper)模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

动机(Motivation):

过多地使用继承来扩展对象的功能,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性,并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多的子类的膨胀(多继承)。如何使“对象功能的扩展”能够根据需要来动态的实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?

 

装饰模式以对客户端透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多的饿子类的情况下,将对象的功能加以扩展。

源代码:

 


// 抽象构件角色的源代码

interface Component {

    /**

     * 商业方法

     */

    void sampleOperation();

}

 

 

 


// 具体构件源代码

class ConcreteComponent implements Component {

   

    public ConcreteComponent() {}

 

    public void sampleOperation() {

      

    }

   

}

 

 

 


// 装饰角色源代码

class Decorator implements Component {

    private Component component;

 

    public Decorator(Component component) {

       this.component = component;

    }

   

    public Decorator() {}

    // 商业方法,委派给构件

    public void sampleOperation() {

       component.sampleOperation();

    }

   

}

 

 


// 具体构件源代码

class ConcreteComponent implements Component {

   

    public ConcreteComponent() {}

 

    public void sampleOperation() {

      

    }

   

}

 

 

对象图:

装饰模式的对象图呈链状结构,其共有三个具体装饰类,分别成为 Decorator1,Decorator2,

Decorator3,具体构件类是ConcreteComponent。一个典型的创建过程如代码。

 

new Decorator1 (

       new Decorator2(

              new Decorator3(

                     new ConcreteComponent()

                     )

              )

       )

);

 

代码分析:

抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。

装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

具体装饰(Concrete Decorator)角色:负责给构件对象“贴上”附加的责任。

 

这就意味着Decorator1的对象持有一个对Decorator2对象的引用,后者则持有一个对Decorator3对象的引用,再后者持有一个具体构件ConcreteComponent对象的引用,这种链式的引用关系式装饰模式看上去像是一个LinkedList.装饰模式常常被称作包裹模式,就是因为每一个具体装饰类都将是下一个具体装饰类或者具体构件类包裹起来。

 

装饰模式应当在什么情况下使用:

在以下情况下应当使用装饰模式:

需要扩展一个类的功能,或给一个类增加附加的责任。

需要动态地给一个对象增加功能,这些功能可以再动态地撤销

需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

使用装饰模式的优点:

装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。

装饰模式允许系统动态地决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系式静态的,它在系统运行前就决定了。

通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加容易出错。

由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较容易实现。但是,在另一方面,使用装饰模式也会产生比使用继承关系更多的对象。更多的对象会使的查错变得困难。

模式实现的讨论:

对装饰模式简化时需要注意以下的情况:

◆     一个装饰类的接口必须与被装饰类的接口相容。ConcreteDecorator类必须与被装饰类的接口相容。

◆     尽量保持Component作为一个“轻”类。

这个类的责任是为ConcreteDecorator类提供共同的接口,因此它应当这种看重在提供接口而不是存储数据。Component可以是一个Java接口,而在实际的工作中,它可以是一个抽象类或者是一个具体类。此时,就应当注意不要把太多的逻辑和状态放在Component类里。

◆     如果只有一个ConcreteComponent类而没有抽象的Component类(接口),那么Decorator类经常可以是ConcreteComponent的一个子类。由此可知没有抽象接口Component也是可以的,但ConcreteComponent就要扮演双重角色。

 

透明性的要求:装饰模式对客户端的透明性的要求程序不要声明一个ConcreteDecorator类型的变量,而应当声明一个Component类型的变量。

 

Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点是在于解决“主体类在多个方向上的扩展功能”。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liyangbing315/archive/2010/01/19/5212695.aspx

 

原创粉丝点击