java 开发模式之十三 : 代理模式

原理或定義

提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是: 可以在目标对象实现的基础上增强额外的功能操作即扩展目标对象的功能

代理模式又分为静态代理和动态代理。静态代理是由程序猿创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理是在程序运行时,通过运用反射机制动态的创建而成。

结构

抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象

類圖

案例与代码

本文使用远程糖果机监控项目作为远程代理的案例

监控糖果机:地点、糖果库存和当前状态


远程代理:远程对象的本地代表,通过它可以让远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。

利用Java RMI实现远程代理:


RMI远程方法调用是计算机之间通过网络实现对象调用的一种通讯机制。
使用这种机制,一台计算机上的对象可以调用另外 一台计算机上的对象来获取远程数据。

RMI开发步骤:

制作远程接口:接口文件
远程接口的实现:Service文件
RMI服务端注册,开启服务
RMI代理端通过RMI查询到服务端,建立联系,通过接口调用远程方法

被监控的机器类:

public class CandyMachine extends UnicastRemoteObject implements CandyMachineRemote{

	State mSoldOutState;
	State mOnReadyState;
	State mHasCoin;
	State mSoldState;
	State mWinnerState;
	private String location="";
	private State state;
	private int count = 0;

	public CandyMachine(String location,int count) throws RemoteException{
		this.location=location;
		this.count = count;
		mSoldOutState = new SoldOutState(this);
		mOnReadyState = new OnReadyState(this);
		mHasCoin = new HasCoin(this);
		mSoldState = new SoldState(this);
		mWinnerState = new WinnerState(this);
		if (count > 0) {
			state = mOnReadyState;
		} else {
			state = mSoldOutState;
		}
	}
	public String getLocation()
	{
		return location;
	}
	public void setState(State state) {
		this.state = state;
	}

	public void insertCoin() {
		state.insertCoin();
	}

	public void returnCoin() {
		state.returnCoin();
	}

	public void turnCrank() {
		state.turnCrank();
		state.dispense();
	}

	void releaseCandy() {

		// TODO Auto-generated method stub
		if (count > 0) {
			count = count - 1;
			System.out.println("a candy rolling out!");
		}

	}

	public int getCount() {
		return count;
	}

	public void printstate() {
		state.printstate();
	}
	public State getstate() {
		return state;
	}
}
此类的设计沿用状态模式的设计方法。


客户端类:

public class RemoteMainTest {
	public static void main(String[] args) {

		try {
			CandyMachine service = new CandyMachine("test1", 7);
			// LocateRegistry.createRegistry(6602);
			Naming.rebind("rmi://127.0.0.1:6602/test1", service);
			service.insertCoin();
			service = new CandyMachine("test2", 5);
			Naming.rebind("rmi://127.0.0.1:6602/test2", service);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.toString());
		}

	}
}




代理接口:

import java.rmi.Remote;
import java.rmi.RemoteException;

import com.java.jikexueyuan.agentmode.candymachine.State;

public interface CandyMachineRemote extends Remote{
	public String  getLocation() throws RemoteException;
	public int getCount() throws RemoteException;
	public State getstate() throws RemoteException;
}


管理类/ 监控类:

public class Monitor {

	private ArrayList<CandyMachineRemote> candyMachinelst;

	public Monitor() {
		candyMachinelst = new ArrayList<CandyMachineRemote>();
	}

	public void addMachine(CandyMachineRemote mCandyMachine) {
		candyMachinelst.add(mCandyMachine);
	}

	public void report() {
		CandyMachineRemote mCandyMachine;
		for (int i = 0, len = candyMachinelst.size(); i < len; i++) {
			mCandyMachine = candyMachinelst.get(i);
			try {
				System.out
						.println("Machine Loc:" + mCandyMachine.getLocation());

				System.out.println("Machine Candy count:"
						+ mCandyMachine.getCount());
				System.out.println("Machine State:"
						+ mCandyMachine.getstate().getstatename());
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}

测试类:

public class MainTest {

	public static void main(String[] args) {
		Monitor mMonitor = new Monitor();

		try {
			CandyMachineRemote mCandyMachine = (CandyMachineRemote) Naming
					.lookup("rmi://127.0.0.1:6602/test1");
			mMonitor.addMachine(mCandyMachine);
			mCandyMachine = (CandyMachineRemote) Naming
					.lookup("rmi://127.0.0.1:6602/test2");
			mMonitor.addMachine(mCandyMachine);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		mMonitor.report();
	}

}




使用場景

1 远程代理,也就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实

2、虚拟代理,是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。这样就可以达到性能的最优化,比如圖片對象。

3、安全代理,控制真实对象访问时的权限。一般用于对象应该有不同的访问权限的时候

4、指针引用,是指当调用真实的对象时,代理处理另外一些事。比如计算真实对象的引用次数,这样当该对象没有引用时,可以自动释放它,或当第一次引用一个持久对象时,将它装入内存,或是在访问一个实际对象前,检查是否已经释放它,以确保其他对象不能改变它。这些都是通过代理在访问一个对象时附加一些内务处理

5、延迟加载,用代理模式实现延迟加载的一个经典应用就在 Hibernate 框架里面。当 Hibernate 加载实体 bean 时,并不会一次性将数据库所有的数据都装载。

優缺點

主要优点有:

1代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用

缺点主要有

1由于在客户端和真实主题之间增加了代理对象,会造成请求的处理速度变慢;

2实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值