Java设计模式(六)---代理模式

x33g5p2x  于2021-03-13 发布在 Java  
字(7.3k)|赞(0)|评价(0)|浏览(640)

英文名称:Proxy Pattern

定义:为其他对象提供一种代理以控制对这个对象的访问。

我的理解:代理模式相当于现实生活中的明星经纪人,提供了一个很好的访问控制。

代理模式的分类:

静态代理模式
--|普通代理模式
--|强制代理模式

动态代理模式

代理模式的一般模式:

###Subject抽象主题角色
--|抽象主题类可以是抽象类也可以是接口,是一个最普通的业务型定义,无特殊要求。

RealSubject具体主题角色

--|也被叫做委托角色、被代理角色。是业务逻辑的具体执行者

Proxy代理主题角色

--|也叫作代理类、委托类。负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实角色实现, 并且在真实主题角色处理完毕后做预处理和善后处理工作。

public class ProxyTest {
	public static void main(String[] args) {
		//实例化一个真实的被委托类。
		System.out.println("---------实例化一个真实的被委托类--------------");
		Proxy realSubject = new Proxy(new RealSubject());
		realSubject.request();
	}
}
interface Subject{
	//定义一个方法,让子类去实现
	public void request();
}
class RealSubject implements Subject{
	//被委托角色,执行具体是方法实现
	@Override
	public void request() {
		System.out.println("我是RealSubject,我在执行方法....");
	}
}
class Proxy implements Subject{
	//代理类,负责真实角色的应用。
	private Subject subject = null;
	//设置想要的被代理者
	public Proxy(Subject subject){
		this.subject = subject;
	}
	@Override
	public void request() {
		before();
		this.subject.request();
		after();
	}
	private void before(){
		System.out.println("代理类,在做事前处理...");
	}
	private void after(){
		System.out.println("代理类,在做善后处理...");
	}
}

##普通代理模式:

--|要求客户端只能访问代理角色,而不能访问真实角色。
一个例子:
一款非常著名的游戏,游戏玩家需要整天的登录、打怪、升级。但是游戏玩家没有时间, 所以他需要找一个代理来替他完成这个重复的过程,并使得游戏技能提升。
--|IGamePlayer游戏玩家接口,定义login(String name,String password)
    killBoss()、upGrade()
--|GamePlayer 游戏玩家,真正的被委托类,实现这些游戏方法。
--|GameProxy 游戏代理,通过代理设置,去委托真实类实现需要的方法。

public class CommonProxy {
	public static void main(String[] args) {
		String name = "xy";
		GameProxy proxy = new GameProxy(name);
		proxy.login(name, "Ilovelzl");
		proxy.killBoss();
		proxy.upGrade();
		System.out.println("-----代理时间到--------");
	}
}
interface IGamePlayer{
	void login(String name,String password);
	void killBoss();
	void upGrade();
}
class GameProxy implements IGamePlayer{
	private GamePlayer gamePlayer = null;
	//通过构造函数来传递要对谁进行游戏代理
	public GameProxy(String name) {
		try {
			this.gamePlayer = new GamePlayer(this, name);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	public void login(String name, String password) {
		this.gamePlayer.login(name, password);
	}

	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	@Override
	public void upGrade() {
		this.gamePlayer.upGrade();
	}
	
}
class GamePlayer implements IGamePlayer{
	private String name="";
	//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
	public GamePlayer(IGamePlayer iGamePlayer,String name)throws Exception {
		if(iGamePlayer == null){
			throw new Exception("不能创建角色");
		}else{
			this.name = name;
		}
	}
	@Override
	public void login(String name, String password) {
		System.out.println("用户:"+this.name+"登录成功!");
	}

	@Override
	public void killBoss() {
		System.out.println(this.name+"在打怪!");
	}

	@Override
	public void upGrade() {
		System.out.println(this.name+"又升了一级...");
	}
	
}

强制代理

---|必须通过真实角色找到代理角色,否则不能访问。
依旧是打怪的例子实现;

public class CommonProxy {
	public static void main(String[] args) {
		//首先创建一个游戏玩家
		System.out.println("------只创建一个玩家,不设置代理的效果---------");
		GamePlayer xy = new GamePlayer("xy");
		xy.login("xy", "pass");
		xy.killBoss();
		xy.upGrade();
		System.out.println("------创建一个玩家,并设置代理的效果---------");
		GameProxy proxy = (GameProxy) xy.getProxy();
		proxy.login("xy", "pass");
		proxy.killBoss();
		proxy.upGrade();
	}
}
interface IGamePlayer{
	void login(String name,String password);
	void killBoss();
	void upGrade();
	IGamePlayer getProxy();
}
class GameProxy implements IGamePlayer{
	private IGamePlayer gamePlayer = null;
	//通过构造函数来传递要对谁进行游戏代理
	public GameProxy(IGamePlayer gamePlayer) {
		this.gamePlayer = gamePlayer;
	}
	@Override
	public void login(String name, String password) {
		this.gamePlayer.login(name, password);
	}

	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	@Override
	public void upGrade() {
		this.gamePlayer.upGrade();
	}
	//设置代理,代理没有具体的实例,因此暂时返回自己。
	@Override
	public IGamePlayer getProxy() {
		// TODO Auto-generated method stub
		return this;
	}
	
}
class GamePlayer implements IGamePlayer{
	private String name="";
	private IGamePlayer proxy = null;
	//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
	public GamePlayer(String name) {
		this.name = name;
	}
	//设置代理
	@Override
	public IGamePlayer getProxy() {
		this.proxy = new GameProxy(this);
		return this.proxy;
	}
	@Override
	public void login(String name, String password) {
		if(this.isProxy()){
			System.out.println("用户:"+this.name+"登录成功!");
		}
		else{
			System.out.println("请使用指定的代理访问...");
		}
	}

	@Override
	public void killBoss() {
		if(this.isProxy()){
			System.out.println(this.name+"在打怪!");
		}
		else{
			System.out.println("请使用指定的代理访问...");
		}
	}

	@Override
	public void upGrade() {
		if(this.isProxy()){
			System.out.println(this.name+"又升了一级!");
		}
		else{
			System.out.println("请使用指定的代理访问...");
		}
	}
	private boolean isProxy(){
		if( proxy == null){
			return false;
		}
			return true;
	}
}

动态代理

public class DynamicProxy {
	public static void main(String[] args) {
		//定义一个游戏玩家
		MyIGamePlayer player = new MyGamePlayer("lzl");
		//定义一个handler
		InvocationHandler handler = new GamePlayIH(player);
		//开始游戏,获得类的classLoader
		ClassLoader cl = player.getClass().getClassLoader();
		//动态产生一个代理者
		 MyIGamePlayer proxy = (MyIGamePlayer)Proxy.newProxyInstance(cl,new Class[]{MyIGamePlayer.class},
				 handler);
		 proxy.login("lzl", "123");
		 proxy.killBoss();
		 proxy.upGrade();
	}
}
interface MyIGamePlayer{
	void login(String name,String password);
	void killBoss();
	void upGrade();
}
class GamePlayIH implements InvocationHandler{
	//设置动态代理,必须继承InvocationHandler接口。并实现invoker方法
	//被代理者
	Class cls = null;
	Object obj = null; 
	public GamePlayIH(Object obj) {
		this.obj = obj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = method.invoke(this.obj, args);
		if(method.getName().equalsIgnoreCase("killBoss")){
			System.out.println("有人用我的账号登录...");
		}
		return result;
	}
	
}
class MyGamePlayer implements MyIGamePlayer{
	private String name="";
	//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
	public MyGamePlayer(String name){
		this.name = name;
	}
	@Override
	public void login(String name, String password) {
		System.out.println("用户:"+this.name+"登录成功!");
	}

	@Override
	public void killBoss() {
		System.out.println(this.name+"在打怪!");
	}

	@Override
	public void upGrade() {
		System.out.println(this.name+"又升了一级...");
	}
}

动态代理的一般模式:
AOP:面向横切面编程。
动态代理实现代理的职责,业务逻辑ISubject实现相关的逻辑给你。
两者时间没有必然的相互耦合关系。
通知Advice从另一个切面切入,最终在高层模块也是ProxyT进行耦合,完成逻辑的封装任务。

public class ProxyT {
	public static void main(String[] args) {
		/*//定义一个主题
		ISubject sub = new MySubject();
		//定义主题代理
		ISubject proxy = SubjectDynamicProxy.newProxyInstance(sub);
		proxy.doSomething();*/
	}
}
interface ISubject{
	void doSomething();
}
class MySubject implements ISubject{
	@Override
	public void doSomething() {
		System.out.println("子类具体实现方法...");
	}
}
interface Advice{
	void someAdvice();
}
class MyAdvice implements Advice{
	//该类用于说明,在
	@Override
	public void someAdvice() {
		System.out.println("一些前言方法...");
	}
}
/**
 * 动态代理的Handler类
 * @author admin
 *
 */
class MyInvocation implements InvocationHandler{
	Object obj = null;
	public MyInvocation(Object obj) {
		this.obj = obj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		return method.invoke(obj, args);
	}
	
}
class SubjectDynamicProxy{
	public static <T> T newProxyInstance(ISubject subject){
		//获取类加载器
		ClassLoader loader = subject.getClass().getClassLoader();
		//获得接口数组
		Class<?>[] interfaces = subject.getClass().getInterfaces();
		//获得handler
		InvocationHandler handler = new MyInvocation(subject);
		return (T)Proxy.newProxyInstance(loader, interfaces, handler);
		
	}
}

也可以将上面的改为SubjectDynamicProxy改为DynamicProxys。

class DynamicProxys{
	@SuppressWarnings("unchecked")
	public static <T> T newProxyInstance(ClassLoader loader,
			    Class<?>[] interfaces,InvocationHandler handler ){
		if(true){
			//执行一个前置通知..
			 new MyAdvice().someAdvice();
		}
		return (T)Proxy.newProxyInstance(loader, interfaces, handler);
	}

相关文章