> 文章列表 > Java设计模式(二十)—— 装饰器模式

Java设计模式(二十)—— 装饰器模式

Java设计模式(二十)—— 装饰器模式

        装饰器模式定义如下:动态的给对象添加一些额外的职责。就功能来说,装饰器模式相比生成子类更为灵活。

适合装饰器模式的情景如下:

程序希望动态地增强类的某个对象的功能,而又不影响该类的其他对象。

一、问题的提出

        在消息日志功能中,接收到的消息可以直接送往屏幕显示,也可以用文件保存。只考虑ILogger的实现类。如下:

public interface ILogger {void log(String msg);
}class ConsoleLogger implements ILogger{@Overridepublic void log(String msg) {System.out.println(msg);}
}class FileLogger implements ILogger{@Overridepublic void log(String msg) {DataOutputStream dos = null;try {dos = new DataOutputStream(new FileOutputStream("d:/log.txt"));dos.writeBytes(msg+"\\r\\n");dos.close();} catch (Exception e) {e.printStackTrace();}}
}

 现在需求分析提出了新要求,接收到的信息先转化为大写字母或转化为XML文档,然后屏幕显示或日志保存。常规思路是利用派生类实现,增加的类如下表:

子类 父类 功能
UpFileLogger FileLogger 转化成大写字母后保存到日志文件中
UpConsoleLogger ConsoleLogger 转化成大写字母后屏幕显示
XMLFileLogger FileLogger 转化成XML格式后保存到日志文件中
XMLConsoleLogger ConsoleLogger 转化成XML格式后屏幕显示

如果需求分析继续变化,则类的数目增加非常快,这时就需要用到装饰器模式。

二、装饰器模式

        装饰器模式利用包含代替继承,动态地给一个对象添加一些额外的功能。如图:

右半部分是采用装饰器模式后新增的类图,具体代码如下:

(1)抽象装饰器类

由于需求分析变化了,但无论怎么变,它终究还是一个日志类,因此Decorator类要从接口ILogger派生,而成员变量logger表名Decorator对象要对已有的logger对象进行装饰

public abstract class Decorator implements ILogger{protected ILogger logger;public Decorator(ILogger logger) {this.logger = logger;}
}

(2)信息大写装饰类

public class UpLogger extends Decorator{public UpLogger(ILogger logger) {super(logger);}@Overridepublic void log(String msg) {//对字符串进行大写“装饰”msg = msg.toUpperCase();//然后执行已有的日志功能logger.log(msg);}
}

(3)测试类

public class Test1 {public static void main(String[] args) throws InterruptedException {ILogger existobj = new FileLogger();ILogger uplogger = new UpLogger(existobj);uplogger.log("hello zy");}
}

结果:

可以看到已经将输入的字符串大写并输出到文件中。