Proxy(代理)模式为对象提供一个代理或者占位来控制对该对象的访问。
适用的场合有几种:
远程代理(RemoteProxy)为一个对象在不同的地址空间提供局部代表。
虚代理(VirtualProxy)根据需要创建开销很大的对象。
保护代理(ProtectionProxy)控制对原始对象的访问。
智能指引(SmartReference)取代了简单的指针,它在访问对象时执行一些附加操作。
load()方法以JFrame对象为参数,用于在指定图像加载完毕之后进行回调。在执行load()方法的时候,它先以LOADING引用的图像对象为参数调用setImage(),然后重新绘制图形显示窗口,最后为自己启动一个单独的线程。而run()方法是在单独的线程中执行的,该方法根据构造器中指定的图像文件名创建一个新的ImageIcon对象,然后以该图像对象为参数调用setImage()方法,最后重绘该窗口。
public interface Rocket extends Remote
{
void boost(double factor) throws RemoteException;
double getApogee() throws RemoteException;
double getPrice() throws RemoteException;
}
public class RocketImpl extends UnicastRemoteObject implements Rocket
{
protected double price;
protected double apogee;
public RocketImpl(double price,double apogee) throws RemoteException{
this.price=price;
this.apogee=apogee;
}
public void boost(double factor){
apogee *= factor;
}
public double getApogee(){
return apogee;
}
public double getPrice(){
return price;
}
}
RocketImpl对象作为服务提供者类运行在服务器上,客户端可以通过运行在本地的代理对象来访问RocketImpl对象的方法。
public class RegisterRocket
{
public static void main(String[] args){
try{
Naming.rebind("rmi://localhost:5000/Biggie",biggie);
System.out.println("Registered biggie");
}catch(Exception e){
e.printStackTrace();
}
}
}
运行RegisterRocket应用程序便可在服务器上创建并运行一个RocketImpl对象biggie。客户端只要能够访问Rocket接口和RocketImpl_stub类,便可以访问远程运行的biggie对象。如果只有一台机器,我们仍然可以测试这个RMI应用程序,不过要在localhost而不是另外一台主机上运行服务器端代码。
public class ShowRocketClient
{
public static void main(String[] args){
try{
Object obj=Naming.lookup("rmi://localhost:5000/Biggie");
Rocket biggie = (Rocket) obj;
System.out.println("Apogee is " + biggie.getApogee());
}catch(Exception e){
System.out.println("Exception while looking up a rocket:");
e.printStackTrace();
}
}
}
RMI的优点在于它使得客户端程序只需与本地代理对象进行交互便可达到与远程对象通信的目的。RMI用户定义了客户端和
获的接口,就可以使用动态代理来包装那个类的实例。
public class ShowDynamicProxy
{
public static void main(String[] args){
Set s = new HashSet();
s = ImpatientProxy.newInstance(s);
s.add(new BadApple("Lemon"));
...
System.out.println("The set contains " + s.size() + " things.");
}
}
待续