装饰模式是为了防止子类过多,而导致体系臃肿。实际操作是:装饰模式持有被装饰的一个对象,进行额外的操作。
装饰模式的例子有:java io 包。buffered流。
代理模式和装饰模式一样,也是扩展功能的,只是他的主要作用是防止对象直接和外界接触。
但就其最终表达的效果来说,和装饰模式是等价的。
然而区别是:代理和被代理对象同属一个抽象类或接口的子类,而装饰类则不用。
代理类是把被代理对象作为参数引用进来,不用改变被代理对象的内部结构和方法。把被代理对象和其他额外操作剥离出来。
而装饰类,是在类内部创建了一个被装饰对象,从而对其进行扩展操作。
代理方法例子:
// 抽象角色:
abstract publicclass Subject {
abstract publicvoid request();
}
// 真实角色:实现了Subject的request()方法
public class RealSubject extends Subject {
public RealSubject() { }
public void request() {
System.out.println( " From real subject. " );
}
}
// 代理角色:
public class ProxySubject extends Subject {
// 以真实角色作为代理角色的属性
private SubjectrealSubject;
public ProxySubject(SubjectrealSubject) {this.realSubject = realSubject }// 该方法封装了真实对象的request方法
public void request() {
preRequest();
realSubject.request(); // 此处执行真实对象的request方法
postRequest();
}
...
}
// 客户端调用:
RealSubject real =new RealSubject();
Subject sub =new ProxySubject(real);
Sub.request();
另外,动态代理:
使用场景,spring的AOP面向切面编程,hadoop中RPC等。
思考:如果有个第三方JAR包,要在其中的某个类的run()中前后添加LOG,
怎么办?注意源码是接触不到的,都是class文件。
这时,我们不能在编译环境中处理,那么只能在运行时中处理。
结果就有了动态代理这一说。
使用动态代理必须要实现InvocationHandler。
InvocationHandler的作用是处理新增的逻辑。
其他的代理类和被代理类,是由反射处理的。
实例如下:
// 抽象角色(之前是抽象类,此处应改为接口):
public interface Subject {
abstract public void request();
}
// 具体角色RealSubject:
public class RealSubject implements Subject {
public RealSubject() {}
public void request() {
System.out.println( " From real subject. " );
}
}
// 代理处理器:
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject() {}
public DynamicSubject(Object obj) {
sub = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println( " before calling " + method);
method.invoke(sub,args);
System.out.println( " after calling " + method);
return null ;
}
}
// 客户端:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Client {
static publicvoid main(String[]args) throwsThrowable {
RealSubject rs =new RealSubject();// 在这里指定被代理类
InvocationHandler ds = new DynamicSubject(rs);
Class cls = rs.getClass();
// 以下是一次性生成代理
Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds );
subject.request();
}
}
// 程序运行结果:
before calling public abstract void Subject.request()
From real subject.
after calling public abstractvoid Subject.request()
另外关于代理模式和装饰模式可以参看以下链接:
http://www.cnblogs.com/machine/archive/2013/02/21/2921345.html