[关闭]
@pastqing 2015-11-12T09:00:53.000000Z 字数 2694 阅读 2773

java设计模式——装饰器模式

java 设计模式


一、装饰器模式(Decorator)的定义

wiki是这样定义装饰器模式的:在面向对象编程的领域,一种动态的往一个类中添加新的行为的设计模式。就功能而言,装饰器模式相比生成子类更加灵活,这样可以给某个对象而不是整个类添加一些功能。

通过装饰器模式可以在运行时扩充一个类的功能。增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。修饰类必须和原来的类有相同的接口。

二、装饰器模式的实现

下面是装饰器的基本类图:
Decorator.png-189.4kB
装饰器模式的基本角色

  1. public interface Component {
  2. public void method();
  3. }
  1. public class ConcreteComponent implements Component{
  2. public void method() {
  3. System.out.println("The basic method");
  4. }
  5. }
  1. public abstract class Decorator implements Component{
  2. protected Component component;
  3. public Decorator(Component component) {
  4. this.component = component;
  5. }
  6. public void method() {
  7. component.method();
  8. }
  9. }
  1. public class ConcreteDecoratorA extends Decorator{
  2. public ConcreteDecoratorA(Component component) {
  3. super(component);
  4. }
  5. public void method() {
  6. //先调用原始方法, 在执行扩展方法
  7. super.method();
  8. System.out.println("DecoratorA add sth");
  9. }
  10. //扩展的其他方法...
  11. public void methodA() {
  12. System.out.println("method A");
  13. }
  14. ...
  15. }

一个装饰类同样可以被另一个装饰器类所装饰。利用组合而不是继承的形式来扩展某个类, 使其更加灵活。

二、装饰器模式的具体应用

我们构造这样一个情景:某个应用的数据访问层上,实现持久化的技术有很多种mybaits,jdbc等等。如此我们设计一个接口:

  1. public interface GenerateInterface<T> {
  2. //创建一条记录
  3. public void save(T data);
  4. //更新一条记录
  5. public void update(T data);
  6. }

不同的ORM技术,我们分别设计两个类:

  1. public class MybatisORM<T> implements GenerateInterface<T> {
  2. @Override
  3. public void save(T data) {
  4. //mybatis save
  5. System.out.println("mybaits save");
  6. }
  7. @Override
  8. public void update(T data) {
  9. //mybatis update
  10. System.out.println("mybatis update");
  11. }
  12. }
  1. public class JdbcORM<T> implements GenerateInterface<T> {
  2. @Override
  3. public void save(T data) {
  4. //insert data into table with jdbc
  5. System.out.println("jdbc save");
  6. }
  7. @Override
  8. public void update(T data) {
  9. //update data to table with jdbc
  10. System.out.println("jdbc update");
  11. }
  12. }

现在新增一个需求,是我们在持久化数据的时候, save or update时同时更新日志,这时候为了不更改原有代码, 也不使用继承,我们采用装饰器模式,定义一个装饰者。

  1. public class LogDecoratorORM <T> implements GenerateInterface<T>{
  2. private GenerateInterface<T> generator;
  3. public LogDecoratorORM(GenerateInterface<T> generator) {
  4. this.generator = generator;
  5. }
  6. private void logSave(T data) {
  7. //to insert log table
  8. System.out.println("log save");
  9. }
  10. private void logUpdate(T data) {
  11. //to update log table
  12. System.out.println("log update");
  13. }
  14. @Override
  15. public void save(T data) {
  16. logSave(data);
  17. generator.save(data);
  18. }
  19. @Override
  20. public void update(T data) {
  21. logUpdate(data);
  22. generator.save(data);
  23. }
  24. }

如此就可以实现需求的变动。

三、JDK中的IO与装饰器模式

JDK中IO体系的设计就是基于装饰器模式的。我们先看个简单的IO体系类图:

InputSteam相当于上面模型的Component
FileInputStream就是InputSteam的实现类了。
BufferedInputSteam, DataInputSteam等就是具体的装饰类了。

四、总结

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注