我们可以将装饰对象的实例设为私有而不是在抽象装饰器中保护吗?

Posted

技术标签:

【中文标题】我们可以将装饰对象的实例设为私有而不是在抽象装饰器中保护吗?【英文标题】:Can we make the instance of the decorated object private instead of protected in an abstract decorator? 【发布时间】:2019-01-03 11:12:20 【问题描述】:

我注意到大多数示例对正在装饰的实例使用 protected。我也可以使用私人的吗?

public abstract class CoffeeDecorator implements Coffee 
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee c) 
        this.decoratedCoffee = c;
    
    // ...

【问题讨论】:

protected 使其可用于子类,这在装饰器模式中是必不可少的。如果是private,子类就不能再访问了 private access 修改后的变量/方法不能被子类访问。 应该使用private final作为被装饰的实例并标记类final 但是为什么子类会访问它呢?装饰器只装饰自己的实例,不是吗? 【参考方案1】:

装饰器模式用作继承的替代方案,有助于添加类附加功能,而无需修改或扩展它本身。

我会用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

【讨论】:

以上是关于我们可以将装饰对象的实例设为私有而不是在抽象装饰器中保护吗?的主要内容,如果未能解决你的问题,请参考以下文章

初探装饰器模式

WPF和Expression Blend开发实例:Adorner(装饰器)应用实例

ES6 - 装饰器 - Decorater

关于何时在 TypeScript 中调用装饰器的困惑

装饰器模式

装饰器模式