设计模式二(结构型模式)
结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式
代理模式(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-->>