代理模式
代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问
/**
* 静态代理
*/
public class StaticProxyDemo {
/**
* 方法接口
*/
interface Method{
void show(String str);
}
class MethodDemo implements Method{
@Override
public void show(String str) {
System.out.println(str);
}
}
/**
* 代理方法
*/
class ProxyMethod{
private Method proxyMethod;
public ProxyMethod() {
this.proxyMethod = new MethodDemo();
}
/**
* 对原有的方法进行增强
* @param str
*/
public void show(String str){
if (str.equals("Hello world")) {
proxyMethod.show(str);
}else {
proxyMethod.show("null");
}
}
}
}
上面所展示的是一般的代理模式,也就是静态代理。静态代理有一个很明显的缺点:如果我们系统中有很多地方需要用到代理,那我们我们则需要写很多代理类。因此有时我们需要使用动态代理:
动态代理
/**
* 动态代理
*/
public class ProxyDemo {
/**
* 方法接口
*/
interface IMethod{
void show(String str);
}
class MethodDemo implements IMethod{
@Override
public void show(String str) {
System.out.println(str);
}
}
/**
* 代理方法
*/
class MethodHandler implements InvocationHandler {
//被代理目标
private Object target;
public Object newProxyInstance(Object target){
this.target = target;
//该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
//第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
//第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
//第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
//根据传入的目标返回一个代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("show")) {
if (args[0].equals("Hello world")) {
method.invoke(target,args);
}else {
args[0] = "";
method.invoke(target,args[0]);
}
}
return null;
}
}
public static void main(String[] args) {
ProxyDemo demo = new ProxyDemo();
MethodHandler handler = demo.new MethodHandler();
IMethod proxy = (IMethod) handler.newProxyInstance(demo.new MethodDemo());
proxy.show("Hello world");
}
}
上面是jdk实现的动态代理,是基于接口实现代理的,使用cglib可以实现基于类的动态代理
优点:扩展性强,对象更智能。
缺点:代理类由于做了很多额外的操作,可能使请求速度变慢。
责任链模式
责任链模式为某个请求创建一个对象链,每个对象依次检查此请求,并对其进行处理,或者将它传给链中的下一个对象。
/**
* 责任链模式
*/
public class ResponsibilityListDemo {
/**
* 责任链父类
*/
abstract class IHandler{
private IHandler successor;
public void setSuccessor(IHandler successor) {
this.successor = successor;
}
public abstract void handlerRequest(String post);
protected final void next(String post){
if(this.successor != null){
this.successor.handlerRequest(post);
}
}
}
/**
* 责任链对象A
*/
class AHandler extends IHandler {
@Override
public void handlerRequest(String post) {
res = post.replace("a", "*");
System.out.println("方法A过滤a:"+res);
next(res);
}
}
/**
* 责任链对象B
*/
class BHandler extends IHandler {
@Override
public void handlerRequest(String post) {
res = post.replace("b","*");
System.out.println("方法B过滤b:"+res);
next(res);
}
}
/**
* 责任链对象C
*/
class CHandler extends IHandler {
@Override
public void handlerRequest(String post) {
res = post.replace("c","*");
System.out.println("方法C过滤c:"+res);
next(res);
}
}
private static String res;
public static void main(String[] args) {
ResponsibilityListDemo demo = new ResponsibilityListDemo();
AHandler aHander = demo.new AHandler();
BHandler bHander = demo.new BHandler();
CHandler cHander = demo.new CHandler();
//建立责任链
aHander.setSuccessor(bHander);
bHander.setSuccessor(cHander);
String post = "abc";
System.out.println("过滤前:"+post);
aHander.handlerRequest(post);
System.out.println("过滤后:"+res);
}
}
总结
责任链模式将常用于过滤器,拦截器,事件(鼠标键盘事件,冒泡事件等)等场景
优点
- 请求者和接收者解耦
- 可以动态的增加或减少责任链上的对象,或者修改顺序
缺点
- 调用者不知道请求可能被哪些类处理,不利于排错
- 用户请求可能被责任链中途拦截,最终未必被真正执行,这点既是优点也是缺点,我们可以利用它做权限控制拦截器。