我注意到大多数示例对正在装饰的实例使用受保护的实例。我也可以使用私人吗?
public abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee c) {
this.decoratedCoffee = c;
}
// ...
}
答案 0 :(得分:3)
装饰器模式用作继承的替代方法,有助于在无需修改或扩展自身的情况下添加类的其他功能。
我将使用private
属性而不使用abstract
类来装饰它。在一个非常简单的示例上进行了演示:
CupOfCoffee.java
final class CupOfCoffee implements Coffee {
public final String prepareCoffee() {
return "Coffee";
}
}
SugarCoffee.java
final class SugarCoffee implements Coffee {
private final Coffee coffee;
public SugarCoffee(final Coffee coffee) {
this.coffee = coffee;
}
public final String prepareCoffee() {
return coffee.prepareCoffee() + " with sugar";
}
}
MilkCoffee.java
final class MilkCoffee implements Coffee {
private final Coffee coffee;
public MilkCoffee(final Coffee coffee) {
this.coffee = coffee;
}
public final String prepareCoffee() {
return coffee.prepareCoffee() + " with milk";
}
}
使用可组合的垂直装饰器演示:
new MilkCoffee(
new SugarCoffee(
new SugarCoffee(
new Coffee()
)
)
).prepareCoffee() // Coffee with sugar with sugar with milk
答案 1 :(得分:0)
因为装饰器只能通过组件接口(在您的情况下为Coffee
)访问其装饰的实例,所以不仅可能,而且还希望在抽象类中将实例私有。进行这项工作的关键是在抽象类中为组件接口的所有方法定义委托方法。这样就可以通过超级调用来访问装饰元素。这是对Nikolas'的回答,它也使用了抽象类:
public interface Coffee { String description(); }
abstract class CoffeeDecorator implements Coffee {
private final Coffee decorated;
public CoffeeDecorator(Coffee decorated)
{ this.decorated = decorated; }
public String description()
{ return decorated.description(); }
}
final class BlackCoffee implements Coffee
{
public String description() { return "Coffee"; }
}
final class MilkDecoration extends CoffeeDecorator
{
public MilkDecoration(Coffee coffee) { super(coffee); }
public String description() { return super.description() + " + milk"; }
}
final class SugarDecoration extends CoffeeDecorator
{
public SugarDecoration(Coffee coffee) { super(coffee); }
public String description() { return super.description() + " + sugar"; }
}
请注意,由于所有接口方法均已实现(作为装饰实例的简单委托),因此从技术上讲,不需要声明抽象装饰器abstract
。但是,这是传达设计意图的一种好方法,该意图是该类将由具体装饰器继承。