代理模式
1.定义
为其他对象提供一种代理以控制对这个对象的访问
2.普通代理
普通代理就是我们要知道代理对象的存在,他要求用户只能去访问代理对象,而不能访问真实对象
类图:
代码:
public interface IGamePlay {
//登录游戏
void login(String user,String password);
//杀怪
void killBoss();
//升级
void updateGrade();
}
被代理对象
public class GamePlay implements IGamePlay {
private String name = "";
//构造函数限制谁能创建对象,并同时传递姓名
public GamePlay(IGamePlay iGamePlay , String name) throws Exception {
if(iGamePlay == null){
throw new Exception("iGamePlay is null");
}else{
this.name = name;
}
}
@Override
public void login(String user, String password) {
System.out.println(this.name+"登录游戏");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪");
}
@Override
public void updateGrade() {
System.out.println(this.name+"升级");
}
}
代理对象
public class GamePlayProxy implements IGamePlay {
private IGamePlay iGamePlay = null;
public GamePlayProxy(String name){
try {
iGamePlay = new GamePlay(this,name);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void login(String user, String password) {
this.iGamePlay.login("kevin","23");
}
@Override
public void killBoss() {
this.iGamePlay.killBoss();
}
@Override
public void updateGrade() {
this.iGamePlay.updateGrade();
}
}
测试:
public class Test {
public static void main(String[] args) {
IGamePlay iGamePlay = new GamePlayProxy("kevin");
iGamePlay.login("kevin","123");
iGamePlay.killBoss();
iGamePlay.updateGrade();
}
}
在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了
真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模
块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的 场合。
3.强制代理
强制代理却是要“强制”,你必须通过真实角色查找到代理角色,否则你不能访 问。甭管你是通过代理类还是通过直接new一个主题角色类,都不能访问,只有通过真实角 色指定的代理类才可以访问,也就是说由真实角色管理代理角色
public interface IGamePlay2 {
//登录游戏
void login(String user,String password);
//杀怪
void killBoss();
//升级
void updateGrade();
//每个人都可以找一下自己的代理
IGamePlay2 getProxy();
}
代理对象:
public class GamePlayProxy2 implements IGamePlay2 {
private IGamePlay2 iGamePlay2 = null;
public GamePlayProxy2(IGamePlay2 iGamePlay2){
this.iGamePlay2 = iGamePlay2;
}
@Override
public void login(String user, String password) {
this.iGamePlay2.login(user, password);
}
@Override
public void killBoss() {
this.iGamePlay2.killBoss();
}
@Override
public void updateGrade() {
this.iGamePlay2.updateGrade();
}
@Override
public IGamePlay2 getProxy() {
return this;
}
}
被代理对象
public class GamePlay2 implements IGamePlay2 {
private String name = "";
private GamePlayProxy2 proxy = null;
public GamePlay2(String name) {
this.name = name;
}
@Override
public void login(String user, String password) {
if(isProxy()) {
System.out.println(this.name+"登录游戏");
}else {
System.out.println("无代理");
}
}
@Override
public void killBoss() {
if(isProxy()) {
System.out.println(this.name+"在打怪");
}else {
System.out.println("无代理");
}
}
@Override
public void updateGrade() {
if(isProxy()) {
System.out.println(this.name + "升级");
}else {
System.out.println("无代理");
}
}
@Override
public IGamePlay2 getProxy() {
this.proxy = new GamePlayProxy2(this);
return this.proxy;
}
//校验是否是代理访问
private boolean isProxy(){
if(this.proxy == null){
return false;
}else{
return true;
}
}
}
测试:
public class Test {
public static void main(String[] args) {
GamePlay2 gamePlay2 = new GamePlay2("kevin");
IGamePlay2 proxy = gamePlay2.getProxy();
proxy.login("kevin","123");
proxy.killBoss();
proxy.updateGrade();
}
}
强制代理的概念就是要从真实角色查找到代理角色,不允 许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本
就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
4.动态代理
动态代理实现有两种方式,JDK 动态代理和 CGlib 动态代理,本文介绍JDK 动态代理
JDK 动态代理:创建动态代理类,实现 InvocationHandler 接口,重写 invoke 方法,在 invoke 方法中通过反射调用被代理类的方法,实现代理。jdk 动态代理只能代理接口,即只能代理接口的实现类
切面类
public class Aspect {
public void before() {
System.out.println("前方法");
}
public void after() {
System.out.println("后方法");
}
}
目标类
public interface Target {
void targetMethod();
}
public class TargetClass implements Target {
@Override
public void targetMethod() {
System.out.println("目标类实现目标方法");
}
}
代理类
public class ProxyClass {
public static Target createProxy(){
final Target targetClass = new TargetClass();
final Aspect aspect = new Aspect();
Target proxy = (Target) Proxy.newProxyInstance(ProxyClass.class.getClassLoader(), targetClass.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
aspect.before();
Object result = method.invoke(targetClass,args);
aspect.after();
return result;
}
});
return proxy;
}
}
测试:
public class Test {
public static void main(String[] args) {
Target target = ProxyClass.createProxy();
target.targetMethod();
}
}