《Java设计模式之代理模式》

《代理模式》

  代理模式:为对象提供一种代理以控制这种对象的访问。在Java中有静态代理和动态代理两种实现方式。

  静态代理:

  拿日本动漫《棋魂》举例,佐为只是灵魂,它要下棋必须通过阿光这个“代理”,我们用代码实现一下:
//Subject
public interface WeiQi {
	void playWeiQi();
}
//RealSubject
public class ZuoWei implements WeiQi {
	@Override
	public void playWeiQi() {
		System.out.println("佐为下围棋");
	}
}
//Proxy
public class Guang implements WeiQi {
	private WeiQi zuoWei;
	
	public Guang() {
		zuoWei = new ZuoWei();
	}
	@Override
	public void playWeiQi() {
                System.out.println("阿光才是真正操作棋子的");
		zuoWei.playWeiQi();
	}
}
//测试
public static void main(String[] args) {
	//客户端调用代理类
	WeiQi guang = new Guang();
	guang.playWeiQi();
}
  再使用动态代理实现上面的例子:
//RealSubject
public class ZuoWei implements WeiQi {
	@Override
	public void playWeiQi() {
		System.out.println("佐为下围棋");
	}
	public static void main(String[] args) {
		WeiQi zuoWei = new ZuoWei();
		WeiQi weiQi = (WeiQi) Proxy.newProxyInstance(zuoWei.getClass().getClassLoader(), new Class[]{WeiQi.class}, new WeiQiInvocationHandler(zuoWei));
		weiQi.playWeiQi();
	}
}
class WeiQiInvocationHandler implements InvocationHandler{
	private WeiQi weiQi;
	public WeiQiInvocationHandler(WeiQi weiQi) {
		this.weiQi = weiQi;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("阿光才是真正操作棋子的");
		method.invoke(weiQi);
		return null;
	}
}
  动态代理之所以被称为动态,就是因为运行时才将它的类创建出来。代码开始执行时,还没有proxy类,它时根据传入的接口而创建的。

  代理模式的应用场景

  1.远程代理:可以作为另一台虚拟机上的本地代表,调用代理的方法,会被代理利用网络和IO转换成远程调用服务,并将结果再通过网络返回给客户端。
//服务接口
public interface Hello extends Remote {
	String sayHello()throws RemoteException;
}
//服务实现类
public class SayHello extends UnicastRemoteObject implements Hello {
	protected SayHello() throws RemoteException {
		//该构造器只是为了抛出异常
		super();
	}
	@Override
	public String sayHello() throws RemoteException {
		return "hello brother";
	}
}
//启动服务
public class MyServer {
	//用于启动服务
	public static void main(String[] args) {
		try {
			Hello hello = new SayHello();
			//设置端口
			LocateRegistry.createRegistry(6601);
			Context namingContext = new InitialContext();
			//向rmi注册服务
			namingContext.rebind("rmi://127.0.0.1:6601/hello", hello);
			System.out.println("服务器已经启动");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
//客户端
public class MyClient {
	public static void main(String[] args) {
		try {
			//从rmi中获取服务
			Hello hello = (Hello) Naming.lookup("rmi://127.0.0.1:6600/hello");
			String str = hello.sayHello();
			System.out.println(str);
		} catch (MalformedURLException | RemoteException | NotBoundException e) {
			e.printStackTrace();
		}
	}
}
  2.虚拟代理:在创建开销比较大的对象时,使用虚拟代理替代该对象,只有当该对象被真正调用的时候才会被创建,提高了程序的启动速度。比如加载HTML页面时,图片是要一个一个下的,此时哪些未打开的图片框就是通过虚拟代理代替了图片。
  3.安全代理:一般是通过动态代理来控制真实对象的访问权限。比如用动态代理作权限验证。
  .....还有很多代理模式,这里就不列举了




猜你喜欢

转载自blog.csdn.net/eragon444668/article/details/76622035