Dav*_*rks 2 java design-patterns decorator
查看以下(简化)类的层次结构:
> Email (base class)
> SimpleEmail extends Email
> HtmlEmail extends Email
Run Code Online (Sandbox Code Playgroud)
我需要修饰Email.send()以添加限制功能.我需要实例化SimpleEmail,HtmlEmail或其他类似的Email子类.
这个模式到底应该是什么样的?我的猜测(需要纠正)如下:
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
Run Code Online (Sandbox Code Playgroud)
我的大脑并没有围绕我如何正确处理我需要"增强"的基类的重要现有子类.大多数示例将其简化为继承问题变得混乱的程度.
这是装饰器模式的简化示例.类层次结构重构为static内部类,以便整个示例包含在一个编译单元中(如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!!!
}
}
Run Code Online (Sandbox Code Playgroud)
所以在这里我们有一个简单Animal的层次结构,与Dog和Cat子类.我们还有一个Normal装饰器 - 也是一个Animal- 只是将所有方法委托给另一个Animal.也就是说,它并没有真正做任何有效的装饰,但它已准备好进行子类化,以便可以添加实际的装饰.
我们这里只有一种方法makeNoise().然后我们有两种实际装饰,Loud和Stuttering.(考虑Animal具有许多方法的情况;然后Normal将是最有价值的).
然后我们有一个keepPokingIt(Animal)方法,它采取任何方式 Animal,并将做它不可告知的事情,直到它makeNoise().在我们的main功能中,我们接着keepPokingIt各种各样的动物,装饰着各种个性特征.请注意,我们甚至可以将一个装饰堆叠在另一个上面.
确切的实现细节可能会有所不同,但这个简化的示例几乎捕获了装饰器模式的本质.
ForwardingCollectionGuava的层次结构在上面的例子中,keepPokingIt只关心它是一个Animal.有时您可能只想戳一个Cat而不是一个Dog,或者以其他方式区分这两种类型.在这些类型的场景中,你会再提供NormalCat,NormalDog等等.
如果你很好地设计你的类型层次结构,这应该不是问题.请记住,您不必为每个实现编写装饰器class,而是为您关心的每种类型编写装饰器.理想情况下,每种类型甚至应该是一种interface而不是具体的class.
例如,考虑Java Collections Framework类型层次结构.我们有:
Guava方便地在这种类型层次结构上促进装饰器模式实现:
abstract class ForwardingCollection<E>
abstract子类ForwardingList<E>,ForwardingSet<E>,ForwardingQueue<E>abstract class ForwardingMap<K,V>请注意,没有ForwardingHashMap<K,V>,或者a ForwardingTreeSet<E>.反正可能没有必要.