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

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

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

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

一、问题的提出

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

public interface ILogger {
    void log(String msg);
}

class ConsoleLogger implements ILogger{

    @Override
    public void log(String msg) {
        System.out.println(msg);
    }
}

class FileLogger implements ILogger{
    @Override
    public 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格式后屏幕显示

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

二、装饰器模式

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

Java设计模式(二十)—— 装饰器模式_第1张图片

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

(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);
    }

    @Override
    public 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");
    }
}

结果:

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

Java设计模式(二十)—— 装饰器模式_第2张图片

 

你可能感兴趣的:(设计模式,java,设计模式,装饰器模式)