使用装饰器设计模式为类的层次结构 [英] Using the decorator design pattern for a hierarchy of classes

查看:134
本文介绍了使用装饰器设计模式为类的层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看以下(简化)的课程层次:

Looking at the following (simplified) hierarchy of classes:

>     Email (base class) 
>     SimpleEmail extends Email
>     HtmlEmail extends Email

我需要装饰Email.send()来添加限制功能。
我需要实例化SimpleEmail,HtmlEmail或Email的其他类似的子类。

I need to decorate Email.send() to add throttling functionality. I need to instantiate SimpleEmail, HtmlEmail or other similar subclasses of Email.

这个模式应该怎么样?
我的猜测(需要纠正的)如下:

What should this pattern look like exactly? My guess (which surly needs correcting) is as follows:

class abstract EmailDecorator
   -> Define a constructor: EmailDecorator(Email component)
   -> Implements all methods of Email and passes values through to component
   -> Adds functionality to send() method
class SimpleEmailDecorator extends EmailDecorator
   -> Define a constructor: SimpleEmailDecorator(SimpleEmail component)
   -> Implement all methods of SimpleEmail and pass through to component
class HtmlEmailDirector extends EmaiDecorator
   -> Same as SimpleEmailDecorator

我的大脑并没有包围我如何正确处理基类中重要的现有子类我需要增强。大多数例子简化了这一点,继承问题变得混乱。

My brain is not wrapping around how I properly deal with important existing subclasses of the base class that I need to "enhance". Most examples simplify it down to a point where the inheritance question becomes muddled.

推荐答案

这是一个简化的例子,装饰图案。类层次结构重构为 static 内部类,以便整个示例包含在一个编译单元中(如在ideone.com上所见):

Here's a simplified example of the decorator pattern. The class hierarchy is restructured as static inner classes so that the whole example is contained in one compilation unit (as seen on ideone.com):

public class AnimalDecorator {

    static abstract class Animal {
        public abstract String makeNoise();
    }   
    static class Dog extends Animal {
        @Override public String makeNoise() { return "woof"; }
    }
    static class Cat extends Animal {
        @Override public String makeNoise() { return "meow"; }
    }

    static class Normal extends Animal {
        protected final Animal delegate;
        Normal(Animal delegate)     { this.delegate = delegate; }
        @Override public String makeNoise() {
            return delegate.makeNoise();
        }
    }
    static class Loud extends Normal {
        Loud(Animal delegate)       { super(delegate); }
        @Override public String makeNoise() {
            return String.format("%S!!!", delegate.makeNoise());
        }       
    }
    static class Stuttering extends Normal {
        Stuttering(Animal delegate) { super(delegate); }
        @Override public String makeNoise() {
            return delegate.makeNoise().replaceFirst(".", "$0-$0-$0-$0");
        }
    }

    public static void keepPokingIt(Animal a) {
        // let's skip the details for now...
        System.out.println(a.makeNoise());
    }
    public static void main(String[] args) {
        keepPokingIt(new Cat());
        // meow

        keepPokingIt(new Stuttering(new Dog()));
        // w-w-w-woof

        keepPokingIt(new Loud(new Cat()));
        // MEOW!!!

        keepPokingIt(new Loud(new Stuttering(new Dog())));
        // W-W-W-WOOF!!!        
    }
}

所以这里我们有一个简单的层次结构,具有 Dog Cat 子类。我们还有一个正常装饰器 - 也是一个 Animal - 只需将所有方法委托给另一个动物。也就是说,它没有真正做任何有效的装饰,但是它已经准备好进行子类化,以便可以添加实际的装饰。

So here we have a simple Animal hierarchy, with Dog and Cat subclasses. We also have a Normal decorator -- also an Animal -- that simply delegates all methods to another Animal. That is, it doesn't really do any effective decoration, but it's ready to be subclassed so that actual decorations can be added.

我们这里只有一种方法, code> makeNoise()。然后,我们有两种实际装饰, Loud Stuttering 。 (考虑 Animal 有很多方法的情况,然后正常将是最有价值的)。

We only have one method here, makeNoise(). We then have two kinds of actual decorations, Loud and Stuttering. (Consider the case where Animal has many methods; then Normal would be most valuable).

然后我们有一个 keepPokingIt(Animal)方法,它采用任何 Animal ,并且将直到它 makeNoise()之后才会执行不可争议的事情。在我们的主要函数中,我们然后是 keepPokingIt 各种动物,装饰着各种个性特征。请注意,我们甚至可以将堆栈一个装饰放在另一个顶部。

We then have a keepPokingIt(Animal) method, which takes ANY Animal, and would do unmentionable things to it until it makeNoise(). In our main function, we then keepPokingIt various kinds of animals, decorated with various personality traits. Note that we can even stack one decoration on top of another.

确切的实现细节可能会有所不同,但是这个简化的例子几乎捕获了

The exact implementation details may vary, but this simplified example pretty much captures the essence of the decorator pattern.

在上面的例子中, keepPokingIt 只关心它是一个 Animal 。有时你可能只想戳一个 Cat 而不是一个 Dog ,或以其他方式区分这两种类型。在这种情况下,您可以提供 NormalCat NormalDog 等。

In the above example, keepPokingIt only cares that it's an Animal. Sometimes you may want to just poke a Cat and not a Dog, or in other ways differentiate the two types. In those kinds of scenarios, you'd then provide NormalCat, NormalDog, etc.

如果您很好地设计类型层次结构,这不应该是一个问题。请记住,您不必为每个实现 class 编写装饰器,而是为每个您关心的类型编写一个装饰器。理想情况下,每个类型甚至应该是接口,而不是具体的

If you design your type hierarchy well, this should not be a problem. Remember that you don't have to write decorators for each implementation class, but rather one for each type that you care about. Ideally, each type should even be an interface rather than a concrete class.

考虑 Java Collections Framework 类型层次结构,适用于例。我们有:

Consider the Java Collections Framework type hierarchy, for example. We have:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆