装饰器设计模式VS继承,运行时VS编译时间

时间:2012-07-26 09:53:51

标签: java inheritance runtime decorator compile-time

我在this page看到了以下评论。我不明白为什么“装饰器关系可以在运行时改变”以及为什么“继承关系在编译时被修复”。

  

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

4 个答案:

答案 0 :(得分:5)

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

另一方面,如果所有三个都是装饰器,那么你可以在同一个过程中以任何顺序装饰它们,例如A(B(C))或C(A(B))。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

使用继承,您必须在编译时显式声明子类及其所有细节,并在此之后修复实现。

答案 3 :(得分:1)

我认为这些例子没有说清楚,装饰者有一个对装饰类的引用,即它使用一个接口,想象你有人在访问'List'的最后一个元素时打印出'The End' ,你可以继承所有实现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);
    }
}