那些你要知道的设计模式之-代理

那些你要知道的设计模式之-代理_第1张图片

一.定义

  1. 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

代理在结构上类似装饰着,但目的不同,装饰者模式为对象加上行为,而代理则是控制访问 代理为另一个对象提供代表,以便客户对对象的访问

二.作用

  • 职责清晰真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理
    完成一件事务,附带的结果就是编程简洁清晰。
  • 高扩展性

三.案例

本章将讲解普通代理和动态代理两种代理方式

  • 普通代理
    大学毕业之后大学生们就开始前往不同的城市参加工作,有些公司提供住房还好,但是这种可能性基本不大,于是乎就得考虑住房问题,这个时候市场上就出现了房屋中介商,专门解决这样类似的问题。下面是简单的示意图
那些你要知道的设计模式之-代理_第2张图片
普通代理模式

IHouse接口有两个方法房屋位置和房屋大小

public interface IHouse {

    //位置
    void location(String address);

    //大小
    void size(int size);
}

实现类House,这个类主要用来实现具体的业务逻辑,这里只打印这些信息,

public class House implements IHouse {

    @Override
    public void location(String address) {
        System.out.println(address);
    }

    @Override
    public void size(int size) {
        System.out.println(size+"平方");
    }

}

下面是代理模式的核心代理类,通过构造函数定义一个需要被代理的对象,同时它还可以具备自己的方法,作为一个房屋代理者,它还可以告诉你租房所需的费用

public class HomeProxy implements IHouse {

    private IHouse house;

    //构造函数定义一个租房
    public HomeProxy() {
        this.house = new House();
    }

    @Override
    public void location(String address) {
        this.house.location(address);
    }

    @Override
    public void size(int size) {
        this.house.size(size);
        cost(size);
    }


    //合计
    public void cost(int size) {
        System.out.println(size * 5 + tip(size)+"$");
    }


    //中介费
    public double tip(int size) {
        return size * 5 * 0.35;
    }

}

我们模拟一下租房的过程,如下所示:

public static void main(String[] args) {

        //创建一个房屋中介商
        IHouse proxy = new HomeProxy(house);
        //租房的位置
        proxy.location("上海");
        //租房的大小
        proxy.size(100);

    }

运行结果如下:
上海
100平方
675.0$
这种模式下通过构造函数定义一个代理对象,进行代理。调用者只需要知道代理类是谁就可以了,结构更加清晰,屏蔽了
真实角色的变更对高层模块的影响,真是角色只需要实现接口,实现具体的业务逻辑,想怎么改就怎么改,提高了扩展性


  • 动态代理

动态代理需要实现InvocationHandler接口产生一个代理对象,InvocationHandler是JDK本身就提供好的的动态代理接口,这里用HomeIH去实现这个接口

public class HomeIH implements InvocationHandler {

    //被代理的实例
    Object obj;

    //我要代理谁
    public HomeIH(Object _obj) {
        this.obj = _obj;
    }

    //调用被代理的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //方法执行之前
        System.out.println("before  " + method.getName());
        //执行被代理的方法
        Object result = method.invoke(this.obj, args);
        return result;
    }
}

这样写之后所有方法都由该Handler来进行处理,所有被代理的方法都由invoke方法去执行,invoke的三个参数分别为proxy(代理对象 ),method(被调用方法),args(被调用方法的参数)还是延续上面的代码,只需将main函数修改如下

 public static void main(String[] args) {

        //被代理实例
        IHouse house = new House();
        //通过构造函数传入到Handler中
        HomeIH handler = new HomeIH(house);
        //动态产生一个代理者
        IHouse proxy = (IHouse) Proxy.newProxyInstance(house.getClass().getClassLoader(),new Class[]{IHouse.class},handler);
        //租房的位置
        proxy.location("上海");
        //租房的大小
        proxy.size(100);

    }

运行之后看结果:
before location
上海
before size
100平方
看到没这就是动态代理,还是通过代理去租房,和普通代理的区别就是,动态代理不用创建代理类,不用实现方法接口,而且更加的灵活,更加的具备扩展性 ,当然,JDK的动态代理有一个需要注意的地方,这里的每个委托类都必须是要有接口的,如果你问我,没有实现接口能不能被代理,我说能

四.总结

代理类不仅仅是一个隔离客户端和委托类的中介。我们还可以借助代理来在增加一些功能,而不需要修改原有代码,完美的体现了开闭原则。
真正的业务功能还是有被代理来实现,但是在实现业务类之前的一些公共服务,或者之后的服务。我们可以通过代理模式来实现

你可能感兴趣的:(那些你要知道的设计模式之-代理)