装饰器模式 - 将装饰器限制为特定类型的组件

时间:2016-09-16 14:58:34

标签: design-patterns decorator

如果装饰器应用于不兼容的组件,您会怎么做?

如果您考虑给出的经典示例来说明模式的使用,即图形窗口,如果您将(如果)滚动条装饰器应用于对话框("对话框"作为具体窗口组件)会发生什么?有固定的尺寸)?或者更确切地说,"应该"发生? (我认为理想情况下不会发生任何事情,至少就滚动条装饰对话框的用户在屏幕上看到的情况而言,但我对策略更感兴趣避免人们做蠢事。)

1 个答案:

答案 0 :(得分:3)

  

但我对避免人们做蠢事的策略更感兴趣

您可以使用marker界面模式实现此目的。

  • 定义名为Scrollable的接口。
  • 支持滚动功能的所有组件都将实现此接口。例如,WindowScrollable,因此应实现此接口。
  • 具体ScrollDecorator实现将具有Scrollable实例变量和带有Scrollable参数的构造函数。
  • 通过使ScrollDecorator构造函数采用Scrollable方法,您现在可以限制ScroallDecorator只能装饰那些Scrollable的实例。

由于这是一个与语言无关的问题,因此“接口”和“实现”这两个词不应与Java编程语言相关联,而应与一般定义相关联。也就是说,这里是Java中讨论的点的编码版本:

让我们先来看看解决方案的最终所需状态:

 Component window =  new ScrollDecorator(new Window());//should be allowed
 Component dialog = new ScrollDecorator(new Dialog());//should not be allowed. 

尝试使用滚动条修饰对话框将导致编译错误。现在让我们看看使这成为可能的类:

组件

public interface Component {
    public void load();
}

可滚动(标记界面)

public interface Scrollable extends Component {

}

具体组件(窗口)

public class Window implements Scrollable {

    @Override
    public void load() {
        //code for drawing a window.        
    }

}

具体组件(对话框)

class Dialog implements Component {

    @Override
    public void load() {
        //code for drawing a dialog.        
    }

}

<强> ScrollDecorator

public class ScrollDecorator implements Component {

    private Scrollable scrollable;

    public ScrollDecorator(Scrollable scrollable) {
        this.scrollable = scrollable;
    }

    @Override
    public void load() {
        scrollable.load();
        //code for drawing a scrollbar over the scrollable component

    }
}

可用于实现此目的的其他语言特定选项是Java中的注释或.NET中的自定义属性。