2

我在这个页面上看到了下面的评论。我不明白为什么“装饰器关系可以在运行时改变”以及为什么“继承关系在编译时是固定的”。

装饰器被证明比继承更灵活,因为装饰器和它们装饰的对象之间的关系可以在运行时改变,但是基类和它们的扩展之间的关系在编译时是固定的

4

4 回答 4

5

如果你有三个类,A、B 和 C,那么无论你如何继承,你都有一个静态关系,例如 A:B 和 B:C。

另一方面,如果这三个都是装饰器,那么您可以在同一进程中以任意顺序装饰它们,例如 A(B(C)) 或 C(A(B))。

于 2012-07-26T10:05:25.480 回答
2

您可以随时装饰对象。假设你有一个,你可以在运行时FileInputStream用它来装饰它。BufferedInputStream如果这是由类继承设计的,您将无法将您的类型转换/转换FileInputStream为任何其他类型。

于 2012-07-26T10:05:41.493 回答
1

使用装饰器,您只需编写一个将对象作为输入并返回某种包装器的方法。装饰器可以任意智能,可以针对不同的输入进行专门的实现,等等。

使用继承,您必须在编译时显式声明子类及其所有细节,然后实现固定。

于 2012-07-26T10:04:57.740 回答
1

我认为这些例子没有说明的是装饰器有一个对装饰类的引用,即它使用一个接口,假设你想在有人访问“列表”的最后一个元素时打印出“结束”,你可以子类化所有实现 List 并具有 'MyArrayList、MyLinkedList、MyCopyOnWriteArrayList 等的类并覆盖 get() 方法,(我相信你会同意)或者你可以使用装饰器并传入实现(即实际列表)在运行时,它被它的接口引用,所以你只有一个新的 get 方法的实现。考虑这个人为的例子(如下),重点是我可以将 List 的任何实现传递给 ListDecorator 并且它会起作用,想象一下通过继承来做到这一点,我相信你

package decorator;

import java.util.ArrayList;
import java.util.List;

public class ListDecorator {

    List realList;
    public static void main(String[] args) {

            // Here we are decorating an ArrayList but it could be anything
            // that implements the List interface.
        ListDecorator ld = new ListDecorator( new ArrayList() );
        for(int i=0; i<10; i++)
            ld.add( i );

        for(int j=0; j<10; j++)
            System.out.println("[j]="+ld.get(j) );
    }
    ListDecorator(List realList){
        this.realList = realList;
    }
    public void add(Object o){
        realList.add( o );
    }
    public Object get(int i){
        if(i == realList.size() -1)
            System.out.println("The end");

        return realList.get(i);
    }
}
于 2013-09-28T16:29:41.633 回答