代理器模式(Proxy)和状态模式(state)都能够提供你应用在你的代码中的代理类。做工作的真正的类隐藏在这个代理类的后面。当你调用代理类中的一个方法,它简单的转向并且调用实现类中的方法。这两个模式是如此的相似以至于代理模式可以被看作状态模式的一个特例。有人试图把这两种模式归结为一种模式叫做代理模式(Surrogate)。但是这个术语“代理器”沿用了很久并且有专门的用意,这也恰恰解释这两种模式不同的原因。
其中基本的思想是简单的:从一个基类,这个代理(Surrogate)沿着这个提供了实现的类中被剥离出来:
当一个代理对象被创建,他会给定一个实现到那里发送所有方法的调用。
结构上,代理器模式和状态模式的区别是简单的:一个代理器只有一个实现,状态可以有多个实现。这两种模式在《设计模式》一书中被认为是截然不同的:代理器是控制访问到它的实现,然而状态模式允许你动态的改变实现,然而你扩展你“控制访问到实现”的观念,这两种模式是完整的符合的。
如果我们按照上面的图表实现代理器模式,看起来这样:
//: proxy:ProxyDemo.java
// Simple demonstration of the Proxy pattern.
package proxy;
import junit.framework.*;
interface ProxyBase {
void f();
void g();
void h();
}
class Proxy implements ProxyBase {
private ProxyBase implementation;
public Proxy() {
implementation = new Implementation();
}
// Pass method calls to the implementation:
public void f() {
implementation.f();
}
public void g() {
implementation.g();
}
public void h() {
implementation.h();
}
}
class Implementation implements ProxyBase {
public void f() {
System.out.println("Implementation.f()");
}
public void g() {
System.out.println("Implementation.g()");
}
public void h() {
System.out.println("Implementation.h()");
}
}
public class ProxyDemo extends TestCase {
Proxy p = new Proxy();
public void test() {
// This just makes sure it will complete
// without throwing an exception.
p.f();
p.g();
p.h();
}
public static void main(String args[]) {
junit.textui.TestRunner.run(ProxyDemo.class);
}
} // /:~
当然,实现类没有必要实现与Proxy同样的接口。当Proxy有时为这个类说话时,就是它所调用的方法到基本的意图满足(注意这里的表述与GOF关于Proxy的定义不一致)。然而,有一个公共的接口是便利的,实现被强迫去满足Proxy需要调用的所有方法。
//: proxy:PoolManager.java
package proxy;
import java.util.*;
public class PoolManager {
private static class PoolItem {
boolean inUse = false;
Object item;
PoolItem(Object item) {
this.item = item;
}
}
public class ReleasableReference { // Used to build the proxy
private PoolItem reference;
private boolean released = false;
public ReleasableReference(PoolItem reference) {
this.reference = reference;
}
public Object getReference() {
if (released)
throw new RuntimeException(
"Tried to use reference after it was released");
return reference.item;
}
public void release() {
released = true;
reference.inUse = false;
}
}
private ArrayList items = new ArrayList();
public void add(Object item) {
items.add(new PoolItem(item));
}
// Different (better?) approach to running out of items:
public static class EmptyPoolItem {
}
public ReleasableReference get() {
for (int i = 0; i < items.size(); i++) {
PoolItem pitem = (PoolItem) items.get(i);
if (pitem.inUse == false) {
pitem.inUse = true;
return new ReleasableReference(pitem);
}
}
// Fail as soon as you try to cast it:
// return new EmptyPoolItem();
return null; // temporary
}
} // /:~
//: proxy:ConnectionPoolProxyDemo.java
package proxy;
import junit.framework.*;
interface Connection {
Object get();
void set(Object x);
void release();
}
class ConnectionImplementation implements Connection {
public Object get() {
return null;
}
public void set(Object s) {
}
public void release() {
} // Never called directly
}
class ConnectionPool { // A singleton
private static PoolManager pool = new PoolManager();
private ConnectionPool() {
} // Prevent synthesized constructor
public static void addConnections(int number) {
for (int i = 0; i < number; i++)
pool.add(new ConnectionImplementation());
}
public static Connection getConnection() {
PoolManager.ReleasableReference rr = (PoolManager.ReleasableReference) pool
.get();
if (rr == null)
return null;
return new ConnectionProxy(rr);
}
// The proxy as a nested class:
private static class ConnectionProxy implements Connection {
private PoolManager.ReleasableReference implementation;
public ConnectionProxy(PoolManager.ReleasableReference rr) {
implementation = rr;
}
public Object get() {
return ((Connection) implementation.getReference()).get();
}
public void set(Object x) {
((Connection) implementation.getReference()).set(x);
}
public void release() {
implementation.release();
}
}
}
public class ConnectionPoolProxyDemo extends TestCase {
static {
ConnectionPool.addConnections(5);
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25966/viewspace-53315/,如需转载,请注明出处,否则将追究法律责任。