设计模式:装饰器模式实现 固定类功能

一年半前写了一篇文章Spring3:AOP,是当时学习如何使用Spring AOP的时候写的,比较基础。这篇文章最后的推荐以及回复认为我写的对你们有帮助的评论有不少,可是如今从我我的的角度来看,这篇文章写得并很差,甚至能够说是没有太多实质性的内容,所以这些推荐和评论让我以为受之有愧。html

基于以上缘由,更新一篇文章,从最基础的原始代码–>使用设计模式(装饰器模式与代理)–>使用AOP三个层次来说解一下为何咱们要使用AOP,但愿这篇文章能够对网友朋友们有益。java

原始代码的写法

既然要经过代码来演示,那必需要有例子,这里个人例子为:设计模式

1
有一个接口Dao有insert、delete、update三个方法,在insert与update被调用的先后,打印调用前的毫秒数与调用后的毫秒数

首先定义一个Dao接口:ide

1
2
3
4
5
6
7
8
9
10
11
12
/**
* @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
*/
public interface Dao {
 
    public void insert();
   
    public void delete();
   
    public void update();
   
}

而后定义一个实现类DaoImpl:函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
*/
public class DaoImpl implements Dao {
 
    @Override
    public void insert() {
        System.out.println( "DaoImpl.insert()" );
    }
 
    @Override
    public void delete() {
        System.out.println( "DaoImpl.delete()" );
    }
 
    @Override
    public void update() {
        System.out.println( "DaoImpl.update()" );
    }
   
}

最原始的写法,我要在调用insert()与update()方法先后分别打印时间,就只能定义一个新的类包一层,在调用insert()方法与update()方法先后分别处理一下,新的类我命名为ServiceImpl,其实现为:学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
*/
public class ServiceImpl {
 
    private Dao dao = new DaoImpl();
   
    public void insert() {
        System.out.println( "insert()方法开始时间:" + System.currentTimeMillis());
        dao.insert();
        System.out.println( "insert()方法结束时间:" + System.currentTimeMillis());
    }
   
    public void delete() {
        dao.delete();
    }
   
    public void update() {
        System.out.println( "update()方法开始时间:" + System.currentTimeMillis());
        dao.update();
        System.out.println( "update()方法结束时间:" + System.currentTimeMillis());
    }
   
}

这是最原始的写法,这种写法的缺点也是一目了然:this

  • 方法调用先后输出时间的逻辑没法复用,若是有别的地方要增长这段逻辑就得再写一遍
  • 若是Dao有其它实现类,那么必须新增一个类去包装该实现类,这将致使类数量不断膨胀

使用装饰器模式

接着咱们使用上设计模式,先用装饰器模式,看看能解决多少问题。装饰器模式的核心就是实现Dao接口并持有Dao接口的引用,我将新增的类命名为LogDao,其实现为:spa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
*/
public class LogDao implements Dao {
 
    private Dao dao;
   
    public LogDao(Dao dao) {
        this .dao = dao;
    }
 
    @Override
    public void insert() {
        System.out.println( "insert()方法开始时间:" + System.currentTimeMillis());
        dao.insert();
        System.out.println( "insert()方法结束时间:" + System.currentTimeMillis());
    }
 
    @Override
    public void delete() {
        dao.delete();
    }
 
    @Override
    public void update() {
        System.out.println( "update()方法开始时间:" + System.currentTimeMillis());
        dao.update();
        System.out.println( "update()方法结束时间:" + System.currentTimeMillis());
    }
 
}

在使用的时候,可使用”Dao dao = new LogDao(new DaoImpl())”的方式,这种方式的优势为:设计

  • 透明,对调用方来讲,它只知道Dao,而不知道加上了日志功能
  • 类不会无限膨胀,若是Dao的其它实现类须要输出日志,只须要向LogDao的构造函数中传入不一样的Dao实现类便可

不过这种方式一样有明显的缺点,缺点为:代理

  • 输出日志的逻辑仍是没法复用
  • 输出日志的逻辑与代码有耦合,若是我要对delete()方法先后一样输出时间,须要修改LogDao

可是,这种作法相比最原始的代码写法,已经有了很大的改进。

相关文章
相关标签/搜索