`

DECORATOR(装饰) -—— 对象机构型模式

 
阅读更多
1、意图
    动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更加灵活。
2、别名
    包装器Wrapper
3、动机
    有时我们希望给某个对象而不是整个类添加一些功能。例如,一个图形用户界面工具箱允许你对任意一个用户界面组件添加一些特性,例如边框,或是一些行为,例如窗口滚动。
    使用继承机制是添加功能的一种有效途径,从其他类继承过来的边框特性可以被多个子类的实例所使用。但这种方式不够灵活,因为边框的选择是静态的,用户不能控制对组件加边框的方式和时机。
    一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框。我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。它将客户请求转发给该组件,并且可能在转发前后执行一些额外的动作(例如画一个边框)。透明性使得你可以递归的嵌套多个装饰,从而可以添加任意多的功能。
    例如,假定有一个对象TextView,它可以在窗口中显示正文。缺省的TextView没有滚动条,因为我们可能有时并不需要滚动条。当需要滚动条时,我们可以用ScrollDecorator添加滚动条。如果我们还想在TextView周围添加一个粗黑边框,可以使用BoarderDecorator添加。因此只要简单地将这些装饰和TextView进行组合,就可以达到预期的效果。
    下面的对象图展示了如何将一个TextView对象与BoarderDecorator以及ScrollDecorator对象组装起来产生一个具有边框和滚动条的文本显示窗口。



   ScrollDecorator和BorderDecorator类是Decorator类的子类。Decorator类是一个可视组件的抽象类,用于装饰其他可视组件,如下图所示:


    VisualComponent是一个描述可视对象的抽象类,它定义了绘制和事件处理的接口。注意Decorator类怎样将绘制请求简单地发送给它的组件,以及Decorator的子类如何扩展这个操作。
    Decorator的子类为特定功能可以自由地添加一些操作。例如,如果其他对象知道界面中恰好有一个ScrollDecorator对象,这些对象就可以用ScrollDecorator对象的ScrollTo操作滚动这个界面。这个模式有一点很重要,它使得在VisualComponent可以出现的任何地方都可以有装饰。因此,客户通常不会感觉到装饰过的组件与未装饰过的组件之间的差异,也不会与装饰产生任何依赖关系。
4、适用性
     以下情况使用Decorator模式
     在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
     处理那些可以撤销的职责。
     当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合奖产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
5、结构




6、参与者
Component(VisualComponent)
    定义一个对象接口,可以给这些对象动态地添加职责。
ConcreteComponent(TextView)
    定义一个对象,可以给这个对象添加一些职责。
Decorator
    维持一个指向Component对象的指针,并定义一个与Component接口一致的接口
ConcreteDecorator(BorderDecorator,ScrollDecorator)
    向组件添加职责
7、协作
    Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。
8、代码示例


First Example (window/scrolling scenario)

The following Java example illustrates the use of decorators using the window/scrolling scenario.
// the Window interface class
public interface Window {
    public void draw(); // draws the Window
    public String getDescription(); // returns a description of the Window
}
 
// extension of a simple Window without any scrollbars
class SimpleWindow implements Window {
    public void draw() {
        // draw window
    }
 
    public String getDescription() {
        return "simple window";
    }
}

The following classes contain the decorators for all Window classes, including the decorator classes themselves.

// abstract decorator class - note that it extends Window
abstract class WindowDecorator implements Window {
    protected Window decoratedWindow; // the Window being decorated
 
    public WindowDecorator (Window decoratedWindow) {
        this.decoratedWindow = decoratedWindow;
    }
    public void draw() {
        decoratedWindow.draw(); //delegation
    }
    public String getDescription() {
        return decoratedWindow.getDescription(); //delegation
    }
}
 
// the first concrete decorator which adds vertical scrollbar functionality
class VerticalScrollBarDecorator extends WindowDecorator {
    public VerticalScrollBarDecorator (Window decoratedWindow) {
        super(decoratedWindow);
    }
 
    @Override
    public void draw() {
        super.draw();
        drawVerticalScrollBar();
    }
 
    private void drawVerticalScrollBar() {
        // draw the vertical scrollbar
    }
 
    @Override
    public String getDescription() {
        return super.getDescription() + ", including vertical scrollbars";
    }
}
 
// the second concrete decorator which adds horizontal scrollbar functionality
class HorizontalScrollBarDecorator extends WindowDecorator {
    public HorizontalScrollBarDecorator (Window decoratedWindow) {
        super(decoratedWindow);
    }
 
    @Override
    public void draw() {
        super.draw();
        drawHorizontalScrollBar();
    }
 
    private void drawHorizontalScrollBar() {
        // draw the horizontal scrollbar
    }
 
    @Override
    public String getDescription() {
        return super.getDescription() + ", including horizontal scrollbars";
    }
}

Here's a test program that creates a Window instance which is fully decorated (i.e., with vertical and horizontal scrollbars), and prints its description:

public class DecoratedWindowTest {
    public static void main(String[] args) {
        // create a decorated Window with horizontal and vertical scrollbars
        Window decoratedWindow = new HorizontalScrollBarDecorator (
                new VerticalScrollBarDecorator(new SimpleWindow()));
 
        // print the Window's description
        System.out.println(decoratedWindow.getDescription());
    }
}


The output of this program is "simple window, including vertical scrollbars, including horizontal scrollbars". Notice how the getDescription method of the two decorators first retrieve the decorated Window's description and decorates it with a suffix.
Second Example (coffee making scenario)

The next Java example illustrates the use of decorators using coffee making scenario. In this example, the scenario only includes cost and ingredients.

// The abstract Coffee class defines the functionality of Coffee implemented by decorator
public abstract class Coffee {
    public abstract double getCost(); // returns the cost of the coffee
    public abstract String getIngredients(); // returns the ingredients of the coffee
}
 
// extension of a simple coffee without any extra ingredients
public class SimpleCoffee extends Coffee {
    public double getCost() {
        return 1;
    }
 
    public String getIngredients() {
        return "Coffee";
    }
}

The following classes contain the decorators for all Coffee classes, including the decorator classes themselves..

// abstract decorator class - note that it extends Coffee abstract class
public abstract class CoffeeDecorator extends Coffee {
    protected final Coffee decoratedCoffee;
    protected String ingredientSeparator = ", ";
 
    public CoffeeDecorator(Coffee decoratedCoffee) {
        this.decoratedCoffee = decoratedCoffee;
    }
 
    public double getCost() { // implementing methods of the abstract class
        return decoratedCoffee.getCost();
    }
 
    public String getIngredients() {
        return decoratedCoffee.getIngredients();
    }
}
 
// Decorator Milk that mixes milk with coffee
// note it extends CoffeeDecorator
class Milk extends CoffeeDecorator {
    public Milk(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }
 
    public double getCost() { // overriding methods defined in the abstract superclass
        return super.getCost() + 0.5;
    }
 
    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Milk";
    }
}
 
// Decorator Whip that mixes whip with coffee
// note it extends CoffeeDecorator
class Whip extends CoffeeDecorator {
    public Whip(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }
 
    public double getCost() {
        return super.getCost() + 0.7;
    }
 
    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Whip";
    }
}
 
// Decorator Sprinkles that mixes sprinkles with coffee
// note it extends CoffeeDecorator
class Sprinkles extends CoffeeDecorator {
    public Sprinkles(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }
 
    public double getCost() {
        return super.getCost() + 0.2;
    }
 
    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Sprinkles";
    }
}


Here's a test program that creates a Coffee instance which is fully decorated (i.e., with milk, whip, sprinkles), and calculate cost of coffee and prints its ingredients:

public class Main {
 
    public static final void main(String[] args) {
        Coffee c = new SimpleCoffee();
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
 
        c = new Milk(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
 
        c = new Sprinkles(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
 
        c = new Whip(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
 
        // Note that you can also stack more than one decorator of the same type
        c = new Sprinkles(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
    }
 
}




  • 大小: 20.8 KB
  • 大小: 54.6 KB
  • 大小: 24.3 KB
分享到:
评论

相关推荐

    装饰者模式——Decorator

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

    装饰模式——装饰模式.doc

    装饰模式是一种设计模式,属于结构型模式,其主要目的是在不改变对象本身的基础上,通过向对象添加新的行为或属性来扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭。 在装饰模式中,有四个关键...

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

    ### C#面向对象设计模式纵横谈(10):Decorator 装饰模式(结构型模式) #### 一、背景介绍 在面向对象编程中,设计模式是一种在特定情况下解决问题的标准化方法。其中,装饰模式(Decorator Pattern)作为结构型模式...

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

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

    23种 设计模式---面向对象的基本原则

    - 装饰模式(Decorator):动态地给一个对象添加一些额外的职责,提供比继承更灵活的功能扩展。 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility):避免将处理请求的发送者和...

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

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

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

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

    设计模式专题之(七)装饰模式---设计模式装饰模式示例代码(python--c++)

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或职责,同时保持对象的接口不变。这种模式使得我们可以在不修改原有代码的基础上,通过组合不同的装饰来扩展对象的功能,实现了代码的高可...

    设计模式精解-GoF 23种设计模式解析附C++实现源码.pdf

    - **2.3 Decorator模式**:装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。 - **2.4 Composite模式**:组合模式允许你将对象组合成树形结构来表示部分整体的层次结构。 - **2.5 Flyweight模式*...

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

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

    decorator-4.2.1-py2.py3-none-any.whl

    decorator-4.2.1-py2.py3-none-any.whl

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

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

    Decorator-3.4.0

    "Decorator-3.4.0" 是一个Python装饰器库的版本,提供了方便和灵活的方式来创建装饰器。这个版本的压缩包文件名为"decorator-3.4.0.tar.gz",它是一个常见的归档格式,用于存储和分发源代码。 在Python中,装饰器...

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    - **2.3 Decorator模式**:动态地给一个对象添加一些额外的职责,提供一种替代继承的灵活方法。 - **2.4 Composite模式**:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户可以以一致的方式处理单个...

    java Decorator装饰模式例子

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

    decorator-4.1.2.rar ,亲测可用

    《Python装饰器深入解析——基于decorator-4.1.2版本》 在Python编程语言中,装饰器(Decorator)是一种强大的工具,它允许我们修改或增强函数、类或其他可调用对象的行为,而无需改动它们的源代码。在本文中,我们...

    PyPI 官网下载 | config_decorator-2.0.10-py3-none-any.whl

    今天我们将深入探讨一个在PyPI上发布的特定资源——config_decorator-2.0.10-py3-none-any.whl。这个资源是一个用于Python开发的库,旨在为开发者提供一种优雅的方式来处理配置装饰器。 首先,让我们解析一下这个...

    设计模式精解-GoF 23 种设计模式解析附 C++实现源码

    创建型模式主要关注对象的创建机制,使得系统能够独立于如何创建、组合那些对象的具体过程。这一部分包括以下几种模式: - **1.1 Factory模式**:定义了一个创建对象的接口,但允许子类决定实例化哪一个类。Factory...

Global site tag (gtag.js) - Google Analytics