代理设计模式

proxy .png

静态代理

  • 抽象主题
public interface Subject {
    void make();
}
  • 真正的主题
public class RealSubject implements Subject {
    @Override
    public void make() {
        System.out.println("执行真正的主题");
    }
}
  • 代理主题
public class ProxySubject implements Subject {
    private Subject subject;
    public ProxySubject(Subject subject) {
        this.subject = subject;
    }
    
    @Override
    public void make() {
        prepare();
        this.subject.make();
        finish();
    }
    
    private void finish() {
        System.out.println("主题结束,收尾");
    }

    private void prepare() {
        // 真正的主题开始之前的准备
        System.out.println("主题开始前的准备");
    }
}

测试:

    @Test
    public void proxyTest() {
        Subject subject = new ProxySubject(new RealSubject());
        subject.make();
    }

这就是静态代理的实现,静态代理中,一个目标对象对应一个代理对象,代理类在编译时期就已经确定了。

静态代理方式总结

可以做到在不修改目标对象的前提下,拓展目标对象的功能。
缺点是:因为代理对象需要同目标对象实现同样的接口,所以会有很多的代理类,造成类过多;并且,一旦接口中增加方法,目标对象同代理对象都需要进行维护。
解决这个缺点的方式就是使用动态代理


动态代理

  • 目标对象接口
public interface IUserDao {
    void save(User user);
}
  • 目标对象类
public class UserDao implements IUserDao {
    @Override
    public void save(User user) {
        System.out.println("保存数据");
        System.out.println(user.toString());
    }
}
  • 动态代理对象
/**
 * 创建动态代理对象
 * 动态代理对象不需要实现接口,但是需要指定接口类型
 */
public class ProxyFactory {
    //维护一个目标对象
    private Object target;
    //对象构造时,提供目标对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        //给目标对象生成代理对象
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("begin transaction");
                        Object returnValue = method.invoke(target, args);
                        System.out.println("Commit Transaction");
                        return returnValue;
                    }
                }
        );
    }
}
  • 测试
    @Test
    public void dynaProxy() {
        IUserDao userDao = new UserDao();

        System.out.println(userDao.getClass());

        IUserDao proxyInstance = (IUserDao) new ProxyFactory(userDao).getProxyInstance();

        System.out.println(proxyInstance.getClass());

        proxyInstance.save(new User("junl",23));
    }

从上面的代码可以看出,动态代理对象不需要实现目标对象接口,但是目标对象一定要实现接口,否则不能使用动态代理。
参考

你可能感兴趣的:(代理设计模式)