DesignPattern_代理模式_07

代理模式

学习自 《设计模式之禅(第二版)》

定义

Provide a surrogate or placeholder for another object tocontrol access to it.
为其他对象提供一种代理以控制对这个对象的访问。
角色:

  • Subject抽象主题角色
    抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
  • RealSubject具体主题角色
    也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。
  • Proxy代理主题角色
    也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
代理模式的优点
  • 职责清晰
    真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。
  • 高扩展性
    具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。
  • 智能化

代码实现

package design.proxy;

/**
 * @author huangqh
 * @create 2020/12/8 16:27
 * @Notes 代理模式
 */
public class Proxy {
}

/**
 * Subject 抽象主题角色
 */
interface IGamePlayer {
    public void login(String name, String password);

    public void killBoss();

    public void upgrade();
}

/**
 * RealSubject 具体主题角色
 */
class GamePlayer implements IGamePlayer {
    private String name = "";

    public GamePlayer(String name) {
        this.name = name;
    }

    @Override
    public void login(String name, String password) {
        System.out.println(String.format("用户名为%s,密码为%s", name, password));
    }

    @Override
    public void killBoss() {
        System.out.println(String.format("%s击杀了boss", this.name));
    }

    @Override
    public void upgrade() {
        System.out.println(String.format("%s升级了", this.name));
    }
}

/**
 * Proxy 代理主题角色
 */
class GamePlayerProxy implements IGamePlayer {

    private IGamePlayer iGamePlayer = null;

    public GamePlayerProxy(IGamePlayer iGamePlayer) {
        this.iGamePlayer = iGamePlayer;
    }

    @Override
    public void login(String name, String password) {
        name = name+222;
        System.out.println("代理类修改参数");
        this.iGamePlayer.login(name, password);
    }

    @Override
    public void killBoss() {
        System.out.println("方法执行前");
        this.iGamePlayer.killBoss();

    }

    @Override
    public void upgrade() {
        this.iGamePlayer.upgrade();
        System.out.println("方法执行后");
    }
}
class Client{
    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("张三");
        IGamePlayer proxy  = new GamePlayerProxy(player);
        proxy.login("张三","123");
        proxy.killBoss();
        proxy.upgrade();
    }
}
普通代理

要求:客户端只能访问代理角色,而不能访问真实角色。
普通代理就是我们要知道代理的存在,也就是类似的GamePlayerProxy这个类的存在,然后才能访问(上列代码简单修改)

package design.proxy;

/**
 * @author huangqh
 * @create 2020/12/8 17:09
 * @Notes  普通代理
 */
public class NormalPorxy {}
interface IGamePlayer {
    public void login(String name, String password);

    public void killBoss();

    public void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name = "";
    public GamePlayer(IGamePlayer gamePlayer,String name){
        if (gamePlayer==null)
            throw new RuntimeException("不能创建真实角色");
        else
            this.name=name;
    }
    @Override
    public void login(String name, String password) {
        System.out.println(String.format("用户名为%s,密码为%s", name, password));
    }

    @Override
    public void killBoss() {
        System.out.println(String.format("%s击杀了boss", this.name));
    }

    @Override
    public void upgrade() {
        System.out.println(String.format("%s升级了", this.name));
    }
}
class GamePlayerProxy implements IGamePlayer {

    private IGamePlayer iGamePlayer = null;

    public GamePlayerProxy(String name) {
        iGamePlayer=new GamePlayer(this,name);
    }

    @Override
    public void login(String name, String password) {
        name = name+222;
        System.out.println("代理类修改参数");
        this.iGamePlayer.login(name, password);
    }

    @Override
    public void killBoss() {
        System.out.println("方法执行前");
        this.iGamePlayer.killBoss();

    }

    @Override
    public void upgrade() {
        this.iGamePlayer.upgrade();
        System.out.println("方法执行后");
    }
}
class Client{
    public static void main(String[] args) {
        IGamePlayer proxy = new GamePlayerProxy("张三");
        proxy.login("张三","123");
        proxy.killBoss();
        proxy.upgrade();
    }
}
强制代理

强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的

package design.proxy;

/**
 * @author huangqh
 * @create 2020/12/8 17:34
 * @Notes 强制代理
 */
public class ForceProxy {
}

/**
 * 强制代理接口
 */
interface IGamePlayer {
    public void login(String name, String password);

    public void killBoss();

    public void upgrade();

    //获取自己的代理
    public IGamePlayer getProxy();
}

/**
 * 强制代理真实角色
 */
class GamePlayer implements IGamePlayer {
    private String name = "";
    private IGamePlayer proxy = null;

    public GamePlayer(String name) {
        this.name = name;
    }

    @Override
    public void login(String name, String password) {
        if (this.isProxy())
            System.out.println(String.format("用户名为%s,密码为%s", name, password));
        else
            System.out.println("请使用代理访问");
    }

    @Override
    public void killBoss() {
        if (this.isProxy())
            System.out.println(String.format("%s击杀了boss", this.name));
        else
            System.out.println("请使用代理访问");
    }

    @Override
    public void upgrade() {
        if (this.isProxy())
            System.out.println(String.format("%s升级了", this.name));
        else
            System.out.println("请使用代理访问");
    }

    @Override
    public IGamePlayer getProxy() {
        this.proxy = new GamePlayerProxy(this);
        return this.proxy;
    }

    private boolean isProxy() {
        if (this.proxy == null)
            return false;
        return true;
    }
}

/**
 * 强制代理的代理类
 */
class GamePlayerProxy implements IGamePlayer {

    private IGamePlayer gamePlayer = null;

    public GamePlayerProxy(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() {
        //代理的代理类还没有,返回自己
        return this;
    }
}

class Client {
    public static void main(String[] args) {
        GamePlayer g1 = new GamePlayer("张三");
        g1.killBoss();      //请使用代理访问
        IGamePlayer proxy = new GamePlayerProxy(new GamePlayer("张三"));
        proxy.killBoss();   //请使用代理访问
        IGamePlayer forceProxy = g1.getProxy();
        forceProxy.killBoss();  //张三击杀了boss
    }
}
动态代理
package design.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author huangqh
 * @create 2020/12/8 18:01
 * @Notes  动态代理
 */
public class IHProxy {
}
/**
 * Subject 抽象主题角色
 */
interface IGamePlayer {
    public void login(String name, String password);

    public void killBoss();

    public void upgrade();
}

/**
 * RealSubject 具体主题角色
 */
class GamePlayer implements IGamePlayer {
    private String name = "";

    public GamePlayer(String name) {
        this.name = name;
    }

    @Override
    public void login(String name, String password) {
        System.out.println(String.format("用户名为%s,密码为%s", name, password));
    }

    @Override
    public void killBoss() {
        System.out.println(String.format("%s击杀了boss", this.name));
    }

    @Override
    public void upgrade() {
        System.out.println(String.format("%s升级了", this.name));
    }
}
class GamePlayIH implements InvocationHandler{
    //被代理者
    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(obj, args);
        return result;
    }

    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("张三");
        InvocationHandler ih = new GamePlayIH(player);
        ClassLoader loader = ih.getClass().getClassLoader();
        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(loader,new Class[]{IGamePlayer.class},ih);
        proxy.killBoss();
    }
}

通用代理框架
package design.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author huangqh
 * @create 2020/12/8 18:18
 * @Notes  通用代理 框架
 */
public class absProxy {
}

/**
 * 抽象主题
 */
interface  Subject{
    //业务操作
    void doSomething(String str);
}

/**
 * 真实主题
 */
class RealSubject implements Subject{
    //业务操作
    @Override
    public void doSomething(String str) {
        System.out.println("do something"+str);
    }
}

/**
 * 动态代理的Handler类
 */
class MyInvocationHandler implements InvocationHandler{
    //被代理的对象
    private Object target = null;
    //通过构造函数传递一个对象
    public MyInvocationHandler(Object obj){
        this.target=obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(this.target,args);
    }
}

/**
 * 动态代理类
 * @param <T>
 */
class DynamicProxy<T>{
    public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler v){
        //寻找JoinPoint连接点,AOP使用元数据定义
        if (true){
            //执行一个前置通知
            (new BeforeAdvice()).exec();
        }
        return (T) Proxy.newProxyInstance(loader,interfaces,v);
    }
}

/**
 * 通知接口
 */
interface IAdvice{
    public void exec();
}

/**
 * 通知实现
 */
class BeforeAdvice implements IAdvice{

    @Override
    public void exec() {
        System.out.println("我被执行了");
    }
}
class Client{
    public static void main(String[] args) {
        //定义一个主题
        Subject subject = new RealSubject();

        //定义一个handler
        InvocationHandler h = new MyInvocationHandler(subject);

        //定义代理主题
        Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass().getInterfaces(), h);

        //代理行为
        proxy.doSomething("Finish");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值