Difference between decorator and proxy patterns

来源:互联网 发布:显卡性能测试软件 编辑:程序博客网 时间:2024/06/07 17:35
 

I had an interesting discussion with a colleague of mine regarding the differences between the proxy and the decorator pattern which made me give it some thought. To the untrained eye (that includes my eye!), they seem exactly the same. Infact you sometimes wonder, why the heck are there two names for the same pattern. As we’ll soon see, they are anything but the same.

I think we’re all aware that the decorator pattern is used to add behavior to existing code. This does not stop at one kind of behavior but any number of different things that we want to do. A proxy on the other hand simply delegates all calls to the underlying object delaying costly operations till they are absolutely neccessary. This basically means that what a proxy can do is decided at compile time and cannot be changed by the calling code after instantiation. Using the decorator pattern the behavior of the underlying object can be changed at runtime by adding multiple decorators to it. This behavior addition takes place at runtime depending on say user input. To put it simply, proxy is compile time, decorator is runtime.

Another very important distinction is that decorators never ever instantiate their surrogate objects. Decorators are always passed their surrogates in their constructors and perform actions on these surrogates.

Proixes on the other hand always obtain an instance of their surrogates (either via constructors or factories). Proxies therefore never really expose their underlying objects but decorators do. For example, consider a badly written legacy file loader class which reads the entire contents of a file. File loader objects are frequently created but rarely used leading to massive memory problem. To resolve this we can use a proxy.

class FileLoader implements Loader {
    privateFile file;
    publicFileLoader(File file) {
        this.file = file;
        readContents(file);
    }
  
    publiclong size() {
        file.length();
   }
   publicbyte[] contents() {
       // return contents
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class FileLoaderProxy implements Loader {
    privateFile file;
    privateFileLoader loader = null;
  
    publicFileLoaderProxy(File file) {
        this.file = file;
        readContents(file);
    }
  
    publiclong size() {
        file.length();
   }
   publicbyte[] contents() {
        if(loader == null)
            loader =new FileLoader(file);
        returnloader.contents();
   }
}
Be Sociable, Share!
原创粉丝点击