我们为什么使用装饰器模式?
使用装饰器模式能在不改变源代码的基础上,对源代码的功能进行拓展,即为一个类添加一些功能,同时又不希望改变这个类原来的结构。我举以下例子进行说明。
例如:我已经完成了一个日志的接口和它的各个实现类,但是这些类只有输出日志到不同地方的功能,LoggerFileSystem能将日志输出到文件系统(磁盘)中,LoggerCloud能将日志输出到云端的某个文件中。现在新需求来了,假如我想要在每条日志输出后顺带输出这条日志的时间,我们把它假设为功能一(functionOne);假如我还想再此基础上输出日志内容,我们把它假设为功能二(functionTwo)。我们为日志添加了功能而我们不想去修改每个实现类的方法,这时候就能使用装饰者模式,为这个接口编写一个装饰类,修饰原来的日志输出。
log()定义日志输出的方法
/**
* Created by AQ on 2018/7/11.
*/
public interface Logger {
public void log();
}
LoggerCloud和LoggerFileSystem为原有的结构(我们未对日志功能进行拓展时已存在)
/**
* Created by AQ on 2018/7/11.
*/
public class LoggerCloud implements Logger {
@Override
public void log() {
System.out.println("Log in Cloud");
}
}
/**
* Created by AQ on 2018/7/11.
*/
public class LoggerFileSystem implements Logger {
@Override
public void log() {
System.out.println("Log in FileSystem");
}
}
为Logger编写一个装饰器,拓展log()的功能,这个装饰类要实现Logger接口并且拥有一个Logger成员
/**
* Created by AQ on 2018/7/11.
*/
public class Decorator implements Logger {
protected Logger logger;
Decorator(Logger logger){
this.logger=logger;
}
@Override
public void log() {
if(logger!=null){
logger.log();
}
}
}
FunctionOne和FunctionTwo的newFunction()即我们想要添加的功能
/**
* Created by AQ on 2018/7/11.
*/
public class FunctionTwo extends Decorator {
FunctionTwo(Logger logger) {
super(logger);
}
@Override
public void log() {
super.log();
functionTwo();
}
public void functionTwo(){
System.out.println("new function two");
}
}
/**
* Created by AQ on 2018/7/11.
*/
public class FunctionOne extends Decorator {
FunctionOne(Logger logger) {
super(logger);
}
public void newFunction(){
System.out.println("new function one");
}
@Override
public void log() {
super.log();
newFunction();
}
}
main方法
public class Main {
public static void main(String[] args) {
Logger logger = new LoggerCloud();
logger.log();
System.out.println();
Logger logger1 = new FunctionOne(logger);
logger1.log();
System.out.println();
Logger logger2 = new FunctionTwo(logger1);
logger2.log();
}
}
输出结果为
Log in Cloud
Log in Cloud
new function one
Log in Cloud
new function one
new function two
结果分析
logger.log()调用的是LoggerCloud类中log()方法,输出 Log in Cloud
logger1.log()调用的是FunctionOne类中的log()方法,先运行super.log(),即FunctionOne的父类Decorator的log()方法,由于在构造logger1时传入的值是logger,所以此时Decorator的log()方法运行的是logger.log(),输出Log in Cloud。然后运行到logger1.log()中的newFunction(),输出new function one。
logger2.log()调用的是FunctionTwo类中的log()方法,先运行super.log(),即FunctionTwo的父类Decorator的log()方法,由于在构造logger2时传入的值是logger1,所以此时Decorator的log()方法运行的是logger1.log(),
输出 Log in Cloud
new function one
然后运行到logger2.log()中的newFunction(),
输出new function two。
本文参考了https://blog.csdn.net/qq_24448899/article/details/78068813