代码改变世界

易学设计模式看书笔记(7) - 代理模式

2017-05-23 16:26  tlnshuju  阅读(203)  评论(0编辑  收藏  举报


代理模式

1.系统日志记录的样例:给系统中的业务逻辑加上日志
(1):最简单直接的做法

public class Test
{
 private Logger logger = Loger.getLogger(this.getClass().getName());

 public void doLgic(String name){

  logger.log(name + "開始业务逻辑处理...");
 
  //业务逻辑处理相关程序
  System.out.println("业务逻辑处理相关程序");
  
  logger.log(name + "业务逻辑处理结束...");
 }
}
有其它的类的业务逻辑也须要记录日志:
public class Test1
{
 private Logger logger = Loger.getLogger(this.getClass().getName());

 public void doLgic(String name){

  logger.log(name + "開始业务逻辑处理...");
 
  //业务逻辑处理相关程序
  System.out.println("业务逻辑处理相关程序");
  
  logger.log(name + "业务逻辑处理结束...");
 }
}


 

这两个类为了记录日志,在处理业务逻辑的代码中增加了有关日志处理的方法,
这些方法增加的模式非常相似。混淆了类的单一职责,有什么办法解决问题?

(2):静态代理

定义一个有业务逻辑的接口类:
public interface Test
{
 public void doLogic(String name);
}
详细的逻辑处理类:
public class TestImpl implements Test
{
 public void doLogic(){
  System.out.println("业务逻辑处理");
 }
}

日志代理类:
public class TestProxy implements Test
{
 private Logger logger = Loger.getLogger(this.getClass().getName());
 private Test test;
 public TestProxy(Test test){
  this.test = test;
 }

 public void doLogic(String name){
  logger.log("開始业务逻辑处理...");
  //业务逻辑处理
  test.doLogic(name);
  logger.log("业务逻辑处理结束...");
 }
}

调用代理类,实现日志输出:

public class Client
{
 public static void main(String[] args){
  TestProxy testProxy = new TestProxy(new TestImpl());
  testProxy.doLogic("小四");
 }
}

通过业务逻辑的代理类来调用详细的业务逻辑,相同实现了日志的记录,
并且把日志的记录和业务逻辑进行了分离,这是静态代理。
存在问题就是:每一个方法都要有一个代理类。假设系统中的每一个类都要日志记录,
那代理类的数量非常多。

解决的方法就是动态代理了。

(3):动态代理

基于JDK的动态代理:

public LogProxy implements InvocationHandler
{
 private Logger logger = Loger.getLogger(this.getClass().getName());
 private Object delegate;//代理对象
 
 public Object bind(Object delegate){
  this.delegate = delegate;
  return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
   delegate.getClass().getInterfaces(),this);
 }

 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
  
  Object result = null;
  try{
   logger.log("開始业务逻辑处理...");
   //业务逻辑处理
   result = method.invoke(delegate,args);
   logger.log("业务逻辑处理结束...");
  }catch(Exception e){
   logger.log(e.toString());
  }

  return result;
 }
}

public class  Client
{
 public static void main(String[] args) 
 {
  LogProxy logProxy = new LogProxy();
  Test test = (Test)logProxy.bind(new TestImpl());
  test.doLogin("小五");
 }
}

JDK的动态代理仅仅能针对接口代理。要实现对类的动态代理能够用cglib的动态代理或者其他类库的。

一般推荐的是面向接口编程。

2.动态代理模式简单介绍:
【定义】
代理模式就是给一个对象提供一个代理对象。由这个代理对象控制对
原对象的引用,使代理对象在原对象和client之间起到一个中介的作用。

【原理】
代理模式主要由三部分组成:
抽象目标类,详细目标类 和代理类。

【使用时机】
当系统须要对某个对象进行额外的控制时。