代理模式

30 阅读2分钟

代理模式的目的

代理模式是一种结构型设计模式,其目的是为了扩展目标对象的功能。

代理模式有三种类型,静态代理,动态代理(JDK代理,接口代理)、Cglib代理(在内存中动态的创建目标对象的子类)

静态代理

静态代理需要先定义接口,被代理对象与代理对象一起实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。

//实体类
public class Tv {
    private String name;
    private String adress;

    public Tv(String name, String adress) {
        this.name = name;
        this.adress = adress;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    @Override
    public String toString() {
        return "Tv{" +
                "name='" + name + ''' +
                ", adress='" + adress + ''' +
                '}';
    }
}
//公司接口
public interface TvCompany {

    /**
     * 生产电视机
     *
     * @return
     */
    Tv produceTV();
}
//公司生产车间
public class TvFactory implements TvCompany{

    @Override
    public Tv produceTV() {
        return new Tv("华为","北京");
    }

}
//代理商
public class TvProxy implements TvCompany {

    private TvFactory factory;

    @Override
    public Tv produceTV() {
        if (factory == null) {
            factory = new TvFactory();
        }
        return factory.produceTV();
    }
}
//消费者拿到通过代理商拿到商品(代理类的使用)
 public static void main(String[] args) {

        TvProxy proxy = new TvProxy();
        Tv tv = proxy.produceTV();
        System.out.println(tv);
    }
  • 优点:静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。
  • 缺点:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。

动态代理

特点:JDK动态代理对象不需要实现接口,只有目标对象需要实现接口。

//接口增加维修功能
public interface TvCompany {

    /**
     * 生产电视机
     *
     * @return
     */
    Tv produceTV();

    /**
     * 维修
     * @return
     */
    Tv repairTV();
}
//工厂增加维修业务
public class TvFactory implements TvCompany {

    @Override
    public Tv produceTV() {
        return new Tv("华为", "北京");
    }

    @Override
    public Tv repairTV() {
        return new Tv("小米", "北京");
    }

}
//新的代理商代理公司业务
public class TvProxyFactory {

    private Object target;

    public TvProxyFactory(Object object) {
        this.target = object;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                System.out.println("TV proxy find factory for tv.... ");
                Object invoke = method.invoke(target, objects);
                return invoke;
            }
        });
    }
}
//用户通过代理商完成购买和维修
public static void main(String[] args) {

        TvFactory taget = new TvFactory();
        TvCompany tvCompany = (TvCompany) new TvProxyFactory(taget).getProxy();
        Tv tv = tvCompany.produceTV();
        Tv tv1 = tvCompany.repairTV();

        System.out.println(tv);

        System.out.println(tv1);
    }
  • 代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。
  • 动态代理的方式中,所有的函数调用最终都会经过 invoke 函数的转发,因此我们就可以在这里做一些自己想做的操作,比如日志系统、事务、拦截器、权限控制等。

Java动态代理只能代理接口,要代理类需要使用第三方的CGLIB等类库