结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式

    1. 代理模式(Proxy)

代理模式就是多一个代理类出来,替原对象进行一些操作
为其他对象提供一个代理以控制对某个对象的访问
使用代理模式,可以将功能划分的更加清晰,有助于后期维护

比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面
希望找一个更熟悉的人去帮你做,此处的代理就是这个意思
public interface Sourceable {  
    public void method();  
}  
public class Source implements Sourceable {  

    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
} 
public class Proxy implements Sourceable {  
    private Source source;  
    public Proxy(){  
        super();  
        this.source = new Source();  
    }  
    @Override  
    public void method() {  
        before();  
        source.method();  
        atfer();  
    }  
    private void atfer() {  
        System.out.println("after proxy!");  
    }  
    private void before() {  
        System.out.println("before proxy!");  
    }  
}  
public class ProxyTest {  
    public static void main(String[] args) {  
        Sourceable source = new Proxy();  
        source.method();  
    }  
}
//输出
before proxy!
the original method!
after proxy!

在Proxy类中不仅执行了委托类Source 的method方法还增加了两个功能

  • 静态代理

    上面例子就是静态代理--

1.为了保持行为的一致性,代理类和委托类通常会实现相同的接口
2.代理类和委托类实现了相同的接口,这样就出现了大量的代码重复
3.代理对象只服务于一种类型(如上的Sourceable )的对象,如果要服务多类型的对象 程序开发中必然会产生许多的代理类
  • 动态代理

    动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象
    在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持

public interface UserManager {
        public void addUser(String userId, String userName);
        public void delUser(String userId);
        public String findUser(String userId);
        public void modifyUser(String userId, String userName);
}
public class UserManagerImpl implements UserManager {
    @Override
    public void addUser(String userId, String userName) {
        System.out.println("UserManagerImpl.addUser");
    }
    @Override
    public void delUser(String userId) {
        System.out.println("UserManagerImpl.delUser");
    }
    @Override
    public String findUser(String userId) {
        System.out.println("UserManagerImpl.findUser");
        return "张三";
    }
    @Override
    public void modifyUser(String userId, String userName) {
        System.out.println("UserManagerImpl.modifyUser");
    }
}
//动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。
//该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类
public class LogHandler implements InvocationHandler {
    // 目标对象
    private Object targetObject;
    //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。            
    public Object newProxyInstance(Object targetObject){
        this.targetObject=targetObject;
        //该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例  
        //第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
        //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
        //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
        //根据传入的目标返回一个代理对象
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(),this);
    }
    @Override
    //关联的这个实现类的方法被调用时将被执行
    /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("start-->>");
        for(int i=0;i<args.length;i++){
            System.out.println(args[i]);
        }
        Object ret=null;
        try{
            /*原对象方法调用前处理日志信息*/
            System.out.println("satrt-->>");
            //-----------调用目标方法-------------
            ret=method.invoke(targetObject, args);
            /*原对象方法调用后处理日志信息*/
            System.out.println("success-->>");
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("error-->>");
            throw e;
        }
        return ret;
    }
}
public class Client {
    public static void main(String[] args){
        LogHandler logHandler=new LogHandler();
        UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());
        //UserManager userManager=new UserManagerImpl();
        userManager.addUser("1111", "张三");
    }
}
//结果
start-->>
1111
张三
satrt-->>
UserManagerImpl.addUser
success-->>

ref:
23种设计模式全解析
JAVA学习篇--静态代理VS动态代理