`

使用Decorator(装饰)模式改善现有软件设计—运行期给对象添加新功能

阅读更多
引用
Decorator模式是一种结构型模式,它的作用是动态得给一个对象添加额外职责。Decorator模式,即Wrapper模式,其强制控制作用是在不改动一个类的代码或者不破坏一个类的接口的情况下为该类添加功能。当你想一个类具有更多功能的时候,使用Decorator模式意味着增加功能后的版本不一定要通过扩展类来重用现有功能。


Decorator模式绝就绝在动态给对象添加新功能。一般我们使用继承的时候,行为是静态指定的,在没有编译前就指定了继承类(子类)可以做些什么。但是Decorator可以在运行时给定行为,是动态的。Decorator提供了比继承更有弹性的替代方案。

Decorator模式的重点就是类型匹配,装饰者与被装饰者之间必须有相同的超类。所以我们还是得使用继承。使用子类继承抽象基类。我们这里去继承抽象类的目的不是为了继承它的行为,目的是为了有正确的类型,也就是类型的匹配。行为来自装饰者和基础组件,或与其它装饰者之间的引用关系。

为什么装饰者能动态的给对象添加新功能,原因就在这里,一般如果直接继承父类的话,那么我们的行为一定就会在编译之前就已经决定,这样一来,我们根本无法给对象添加新功能,但是使用了装饰者模式,我们又使用了对象与对象之间的组合,之后结果就完全不一样了。我们会写这样的代码:

File file=new File(path);    
BufferedReader br=new BufferedReader(new FileReader(file));   


这个代码里面就是把file对象往FileReader里装,之后再把FileReader往BufferedReader装。进行一层一层的装饰。

装饰者模式有一套属于自己的设计思路。如下:




Component(被装饰对象基类) :定义对象的接口(也可以是抽象类),可以给这些对象动态增加职责;
ConcreteComponent(具体被装饰对象) :定义具体的对象,Decorator可以给它增加额外的职责;
Decorator(装饰者抽象类): 维护一个指向Component实例的引用,并且定义了与Component一致的接口;
ConcreteDecorator(具体装饰者) :具体的装饰对象,给内部持有的具体被装饰对象增加具体的职责;

引用
Decorator是装饰者模式里非常特殊的一个类,它既继承于Component【IS A关系】,又维护一个指向Component实例的引用【HAS A关系】,换个角度来说,Decorator跟Component之间,既有动态组合关系又有静态继承关系,WHY? 这里为什么要这么来设计?上面我们说过,组合的好处是可以在运行时给对象增加职责,Decorator【HAS A】Component的目的是让ConcreteDecorator可以在运行时动态给ConcreteComponent增加职责,这一点相对来说还比较好理解;那么Decorator继承于Component的目的是什么?在这里,继承的目的只有一个,那就是可以统一装饰者和被装饰者的接口,换个角度来说,不管是ConcretComponent还是ConcreteDecorator,它们都是 Component,用户代码可以把它们统一看作Component来处理,这样带来的更深一层的好处就是,装饰者对象对被装饰者对象的功能职责扩展对用户代码来说是完全透明的,因为用户代码引用的都是Component,所以就不会因为被装饰者对象在被装饰后,引用它的用户代码发生错误,实际上不会有任何影响,因为装饰前后,用户代码引用的都是Component类型的对象,这真是太完美了!装饰者模式通过继承实现统一了装饰者和被装饰者的接口,通过组合获得了在运行时动态扩展被装饰者对象的能力。

     生活中的例子,俗话说“人在衣着马在鞍”,把这就话用装饰者模式的语境翻译一下,“人通过漂亮的衣服装饰后,男人变帅了,女人变漂亮了;”。对应上面的类图,这里人对应于ConcreteComponent,而漂亮衣服则对应于ConcreteDecorator;换个角度来说,人和漂亮衣服组合在一起【HAS A】,有了帅哥或美女,但是他们还是人【IS A】,还要做人该做的事情,但是可能会对异性更有吸引力了(扩展功能)!   


以下代码取自《HEAD FIRST 设计模式》。

Beverage还是所有饮料的基类,它对应于装饰者模式类图里的Component,是所有被装饰对象的基类;HouseBlend, DarkRoast, Espresso, Decaf是具体的饮料(咖啡)种类,对应于前面的ConcreteComponent,即是具体的被装饰对象;CondimentDecorator对应于前面的Decorator,是装饰者的抽象类;而Milk,Mocha,Soy,Whip则都是具体的调味品,对于前面的ConcreteDecorator,也就是具体的装饰者。




package moshi.decorator;

public abstract class Beverage {

	  public String description="Unknown Beverage";  
      
      /* 
       * getDescription()已经在此实现了,但是cost()必须在子类中实现 
       */  
      public String getDescription() {  
          return description;  
      }  
        
      public abstract double cost();  
}

package moshi.decorator;

public abstract class CondimentDecorator extends Beverage {

	//所有的调料装饰者都必须重新实现getDescription()方法.  
    public abstract String getDescription();  

}

package moshi.decorator;

public class Espresso extends Beverage {

	public Espresso(){
		description="Espresso";
	}
	
	
	public double cost() {
		return 1.99;
	}

}


package moshi.decorator;

public class HouseBlend extends Beverage {

	public HouseBlend(){
		description="House Blend Coffee";  
	}
	
	
	public double cost() {
		return .89;
	}

}


package moshi.decorator;

public class Mocha extends CondimentDecorator {

	Beverage beverage;
	
	public Mocha(Beverage beverage){
		this.beverage=beverage;
	}
	

	public String getDescription() {
		return beverage.getDescription()+"Mocha";
	}

	
	public double cost() {
		return .20+beverage.cost();
	}

}


package moshi.decorator;

public class Test {

	public static void main(String[] args) {
		Beverage beverae =new Espresso();
		System.out.println(beverae.getDescription()+"$"+beverae.cost());

		
		Beverage beverae1 =new Espresso();
		beverae1 =new Mocha(beverae1);
		beverae1 =new Mocha(beverae1);
		System.out.println(beverae1.getDescription()+"$"+beverae1.cost());
	}

}


这段代码很明显,说明了Decorator模式,就从Test类来看。
public static void main(String[] args) {
		Beverage beverae =new Espresso();
		System.out.println(beverae.getDescription()+"$"+beverae.cost());

		
		Beverage beverae1 =new Espresso();
		beverae1 =new Mocha(beverae1);
		beverae1 =new Mocha(beverae1);
		System.out.println(beverae1.getDescription()+"$"+beverae1.cost());
	}


我们一开始只NEW了一个Espresso(),因为Espresso类继承了抽象Beverage类,实现了COST方法,我们自然打印出Espresso的钱。

之后,我们又NEW了一个Espresso(),这下情况有所不一样,我们使用了2个Mocha去往Espresso装饰对象,这里已经说名了下面这段代码为什么要取得Beverage引用。

public class Mocha extends CondimentDecorator {

	Beverage beverage;
	
	public Mocha(Beverage beverage){
		this.beverage=beverage;
	}
	

	public String getDescription() {
		return beverage.getDescription()+"Mocha";
	}

	
	public double cost() {
		return .20+beverage.cost();
	}

}


就因为我们取得了beverage,而且 cost()又实现了 return .20+beverage.cost();,自然返回的是Espresso+0.2的值了。


部分内容选自:http://www.cnblogs.com/justinw/archive/2007/06/11/779356.html
  • 大小: 4.1 KB
  • 大小: 25.6 KB
分享到:
评论

相关推荐

    C#设计模式之Decorator 装饰模式

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它在不改变原有对象的基础上,通过添加额外的职责来扩展对象的功能。在C#中,装饰模式尤其适用于那些需要动态地增加或减少对象功能的情况,避免了使用...

    设计模式之装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern)是一种结构型设计模式,它在不改变原有对象的基础上,通过包裹一个对象并为其添加新的行为或责任,实现对对象功能的扩展。这种模式在软件开发中非常常见,尤其当需要在运行时动态改变...

    java Decorator装饰模式例子

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它允许在运行时给对象添加新的行为或职责,而无需改变对象的类。在Java中,装饰模式通常通过继承和组合来实现,使得代码具有更好的扩展性和灵活性。...

    Java设计模式之-Decorator装饰模式

    Decorator模式,也称为装饰模式,是设计模式中的一个重要组成部分,它在不改变原有对象接口的前提下,动态地给对象添加新的功能,从而扩展了对象的能力。这篇博客()将深入探讨这个模式的细节。 装饰模式的核心...

    c++-设计模式之装饰模式(Decorator)

    装饰模式(Decorator Pattern)是一种结构型设计模式,允许在不改变对象接口的情况下,动态地为对象添加额外的职责或功能。装饰模式通常用于需要扩展对象功能而又不希望使用子类化的场景。 装饰模式的组成 组件接口...

    设计模式之 Decorator模式和代码实现

    【Decorator模式】是一种设计模式,它允许在运行时动态地给对象添加新的责任或功能,而不必通过子类化的方式。在上述的奇幻RPG游戏中,Decorator模式被用来实现武器的锻造过程,尤其是武器镶嵌宝石的功能。这个过程...

    设计模式C++学习之装饰模式(Decorator)

    装饰模式(Decorator)是软件设计领域中一种非常实用的结构型设计模式,它允许我们向一个对象添加新的行为或责任,而无需修改该对象的源代码。在C++编程语言中,装饰模式常用于动态地扩展类的功能,使得类的行为在...

    C#面向对象设计模式纵横谈(10):Decorator 装饰模式(结构型模式)

    其中,装饰模式(Decorator Pattern)作为结构型模式之一,在不改变现有对象的情况下为其添加新的功能。本文档通过一个具体的示例——游戏中的坦克,探讨了如何使用装饰模式来动态地增加对象的功能。 #### 二、问题...

    C#面向对象设计模式纵横谈(10):Decorator 装饰模式(结构型模式) (Level 300)

    装饰模式是一种结构型设计模式,它允许我们向一个对象添加新的功能或增强现有功能,而无需改变该对象的类。在C#中,装饰模式通常通过继承和组合来实现,它提供了一种灵活的方式来动态地改变对象的行为。在这个“C#...

    装饰者模式——Decorator

    装饰者模式(Decorator)是一种设计模式,用于在运行时动态地给对象添加额外的责任或功能。它是结构型设计模式的一种,能将行为的增加与对象的创建分离,使得我们可以独立地扩展对象的功能。 在Java或其他面向对象...

    装饰器(Decorator)模式

    使用装饰器模式的时机是当我们需要在不修改原有对象的情况下,动态地给对象添加一些额外的功能时。例如,在设计一个三明治小店的程序时,我们可能需要设计各种三明治的对象,其中包括带蔬菜、沙拉、咸肉等等的三明治...

    Decorator装饰者模式

    装饰者模式是一种面向对象的设计模式,它允许在运行时向对象添加新的行为或属性,而无需修改对象的原始代码。这种模式是结构型模式的一种,遵循开闭原则,即对扩展开放,对修改关闭。Head First系列的学习笔记是通过...

    [结构型模式] head first 设计模式之装饰者模式(decorator)

    装饰者模式(Decorator Pattern)是结构型设计模式之一,它允许在运行时向对象添加新的行为或职责,而无需修改对象的源代码。这个模式的名字来源于装饰艺术,它通过添加额外的装饰来增强一个物体的外观,同样地,...

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

    装饰模式(Decorator)是软件设计模式中的一种结构型模式,其主要目的是在不改变对象原有类的基础上,通过添加新的行为或职责来扩展对象的功能。这种模式使得代码的扩展性非常优秀,避免了由于频繁地使用继承而导致...

    装饰器模式[Decorator]

    装饰器模式(Decorator)是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式属于结构型模式,是面向对象设计中的一种非常实用的技术。 装饰器模式的核心思想是通过将一个...

    设计模式 t07Decorator

    总结来说,“设计模式 t07Decorator”着重介绍的是如何使用装饰者模式来动态地扩展对象的功能,它强调了面向对象设计中的灵活性和可扩展性,是软件开发中一个重要的设计原则和工具。通过理解和应用装饰者模式,我们...

    PHP设计模式(八)装饰器模式Decorator实例详解【结构型】

    装饰器模式(Decorator Pattern)是一种结构型设计模式,主要用于在运行时动态地给对象添加新的职责或行为,而不必改变现有对象的类定义。在面向对象编程中,装饰器模式提供了一种相对于继承更加灵活的方式来增强或...

    设计模式--装饰者模式java例子

    装饰者模式是软件设计模式中的一种结构型模式,它的主要目的是动态地给对象添加新的功能,而无需修改原有代码。在Java中,装饰者模式通常通过继承和组合来实现,它提供了一种比继承更灵活的方式来扩展对象的功能。...

Global site tag (gtag.js) - Google Analytics