设计模式(六)—代理模式

最后更新于:2022-04-01 16:26:04

**英文名称:Proxy Pattern** **定义**:为其他对象提供一种代理以控制对这个对象的访问。 **我的理解**:代理模式相当于现实生活中的明星经纪人,提供了一个很好的访问控制。 **代理模式的分类:** 静态代理模式 --|普通代理模式 --|强制代理模式 动态代理模式 ## 代理模式的一般模式:![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409246a2.jpg) ###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 游戏代理,通过代理设置,去委托真实类实现需要的方法。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_575534093bb69.jpg) ~~~ 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; } } ~~~ ### 动态代理 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409549fa.jpg) ~~~ 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进行耦合,完成逻辑的封装任务。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409728ad.jpg) ~~~ 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); } ~~~
';