设计师网站有哪些销售定制家具,自己可以做电子商务网站,农村自建房设计图大全,html网站的规划与建设6- 定义
在解析动态代理模式之前#xff0c;先简单看下整个代理模式。代理模式分为普通代理、强制模式、动态代理模式。其中动态代理模式主要实现方式为Java JDK提供的JDK动态代理#xff0c;第三方类库提供的#xff0c;例如CGLIB动态代理。 代理模式就是为其他对象提供一种…- 定义
在解析动态代理模式之前先简单看下整个代理模式。代理模式分为普通代理、强制模式、动态代理模式。其中动态代理模式主要实现方式为Java JDK提供的JDK动态代理第三方类库提供的例如CGLIB动态代理。 代理模式就是为其他对象提供一种代理以控制对这个对象的访问。
- 通用类图 - 代理模式的优点
* 职责清晰
真实的角色就是实现实际的业务逻辑不用关心其他非职责的事务通过后期的代理完成一件事务附带的结果就是编程简洁清晰。
* 高扩展性
具体主题角色是随时都会发生变化的只要它实现了接口甭管它如何变化都逃不脱如来佛的手掌(接口)那我们的代理类完全就可以在不做任何修改的情况下使用。
* 智能化
一个类可以实现多个接口完成不同任务的整合。也就是说代理类不仅可以实现主题接口也可以实现其他接口完成不同的任务而且代理的目的是在目标对象方法的基础上作增强这种增强的本质通常就是对目标对象的方法进行拦截和过滤。
- 普通代理
* 定义
定义普通代理就是我们要知道代理的存在也就是类似的GamePlayerProxy这个类的存在然后才能访问;在该模式下调用者只知代理而不用知道真实的角色是谁屏蔽了 真实角色的变更对高层模块的影响真实的主题角色想怎么修改就怎么修改对高层次的模 块没有任何的影响只要你实现了接口所对应的方法该模式非常适合对扩展性要求较高的 场合。当然在实际的项目中一般都是通过约定来禁止new一个真实的角色这也是一个 非常好的方案。
* 类图 * 普通代理包含的角色
真实类被代理类实际完成业务逻辑的类代理类
* 下面来看看具体的演示代码
#IGamePlayer接口
public interface IGamePlayer {void login();void killBoss();void upgrade();
}# GamePlayer类
package com.zoujieli.design.mode.proxy.general;public class GamePlayer implements IGamePlayer{private String name null;public GamePlayer(IGamePlayer gamePlayer, String name) {if (gamePlayer null) {throw new RuntimeException(不能创建真实对象);}this.name name;}Overridepublic void login() {System.out.println(name 登陆游戏了);}Overridepublic void killBoss() {System.out.println(name 开始打BOSS了);}Overridepublic void upgrade() {System.out.println(name 升级了);}
}#代理类
package com.zoujieli.design.mode.proxy.general;//普通代理模式
public class GamePlayerProxy implements IGamePlayer{private GamePlayer gamePlayer;public GamePlayerProxy(String name) {this.gamePlayer new GamePlayer(this, name);}Overridepublic void login() {this.gamePlayer.login();}Overridepublic void killBoss() {this.gamePlayer.killBoss();}Overridepublic void upgrade() {this.gamePlayer.upgrade();}
}
# 场景类 clientpublic class Client {public static void main(String[] args) {GamePlayerProxy proxy new GamePlayerProxy(张三);proxy.login();proxy.killBoss();proxy.upgrade();}
}普通代理是比较简单的一种代理模式
- 强制代理
* 定义
强制代理则 是调用者直接调用真实角色而不用关心代理是否存在其代理的产生是由真实角色决定。
* 类图1代理类实现了单个接口 * 类图2代理类实现了多个接口 下面看看具体演示代码
#业务接口类public interface IGamePlayer {void login();void killBoss();void upgrade();IGamePlayer getProxy();
}
# 被代理类public class GamePlayer implements IGamePlayer {private String name null;private IGamePlayer proxy null;public GamePlayer(String name) {this.name name;}Overridepublic void login() {if (this.proxy null) {throw new RuntimeException(请使用代理者);}System.out.println(name 登陆游戏了);}Overridepublic void killBoss() {if (this.proxy null) {throw new RuntimeException(请使用代理者);}System.out.println(name 开始打BOSS了);}Overridepublic void upgrade() {if (this.proxy null) {throw new RuntimeException(请使用代理者);}System.out.println(name 升级了);}Overridepublic IGamePlayer getProxy() {this.proxy new GamePlayerProxy(this);return this.proxy;}
}
#代理类//普通代理模式
public class GamePlayerProxy implements IGamePlayer, IProxy{private GamePlayer gamePlayer;public GamePlayerProxy(GamePlayer gamePlayer) {this.gamePlayer gamePlayer;}Overridepublic void login() {this.gamePlayer.login();}Overridepublic void killBoss() {this.gamePlayer.killBoss();}Overridepublic void upgrade() {this.gamePlayer.upgrade();this.count();}Overridepublic IGamePlayer getProxy() {return this;}Overridepublic void count() {System.out.println(代练费100);}
}
# 代理接口类public interface IProxy {void count();
}- 动态代理
* 定义
动态代理是在实现阶段不用关心代理谁而在运行阶段 才指定代理哪一个对象。相对来说自己写代理类的方式就是静态代理。
* 类图 类图说明其中invoke方法是接口InvocationHandler定义必须实现的它完成对真实方法的调用。我 们来详细讲解一下InvocationHandler接口动态代理是根据被代理的接口生成所有的方法 也就是说给定一个接口动态代理会宣称“我已经实现该接口下的所有方法了”那各位读者 想想看动态代理怎么才能实现被代理接口中的方法呢?默认情况下所有的方法返回值都是 空的是的代理已经实现它了但是没有任何的逻辑义那怎么办?好办通过 InvocationHandler接口所有方法都由该Handler来进行处理即所有被代理的方法都由 InvocationHandler接管实际的处理任务。 下面是JDK提供的InvocationHandler
public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}* 类图2 这个类图中增加了Iadvice接口作用是在调用业务方法的时候加入通知。这是两条独立发展的线路。动态代理实现代理的职责业务逻辑Subject实现相关的 逻辑功能两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入最终在高层模块也就是Client进行耦合完成逻辑的封装任务。
* 类图2的调用过程如下 类图2的代码演示
public class GamePlayer implements IGamePlayer {private String name null;public GamePlayer(String name) {this.name name;}Overridepublic void login() {System.out.println(name 登陆游戏了);}Overridepublic void killBoss() {System.out.println(name 开始打BOSS了);}Overridepublic void upgrade() {System.out.println(name 升级了);}
}public interface IGamePlayer {void login();void killBoss();void upgrade();
}public class GamePlayerInvocationHandler implements InvocationHandler {Object obj null;public GamePlayerInvocationHandler(Object o) {this.obj o;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object invoke method.invoke(this.obj, args);if (method.getName().equals(login)) {System.out.println(有人在用我的账号登录!);}return invoke;}
} import java.lang.reflect.Proxy;public class DynamicProxy {public static T T newProxyInstance(IGamePlayer gamePlayer) {if (true) {new BeforeAdvice().beforeAdvice();}T proxy (T) Proxy.newProxyInstance(gamePlayer.getClass().getClassLoader(),gamePlayer.getClass().getInterfaces(),new GamePlayerInvocationHandler(gamePlayer));return proxy;}
}
public interface IAdvice {void beforeAdvice();
}public class BeforeAdvice implements IAdvice{Overridepublic void beforeAdvice() {System.out.println(前置通知调用了);}
}
public class Client {public static void main(String[] args) {GamePlayer player new GamePlayer(张三);IGamePlayer proxy DynamicProxy.newProxyInstance(player);proxy.login();proxy.killBoss();proxy.upgrade();}
}调试时只要看到类似$Proxy0这样的结构你就应该知道这是一 个动态代理了。