Java装饰者模式

问题提出

关于日志消息,我们须要将其输出到屏幕或者是日志文档内,于是我们会写几个类:

  • 接口ILogger
  • 类ConsoleLogger负责将信息输出到Console
  • 类 FileLogger负责将信息输出到文件里

可是问题在于。假设我们要对这两个输出类添加条件。比方“将信息转为大写”,“将信息转换成html格式输出”,那么两个类都要被该写成四个类才满足需求。假设要求很多其它,那么类的数目添加的会很快。此时应该使用装饰者模式。

import java.io.*;
import java.util.*;

//接口ILogger
interface ILogger{
    void log(String msg);//抽象的输出方法,可是未指定输出位置,由其对应的实现类来决定
}

//ConsoleLogger。实现了接口。用于将信息输出到屏幕
class ConsoleLogger implements ILogger{
    public void log(String msg){
        System.out.println(msg);
    }
}

//FileLogger,实现了接口。用于将信息输出到日志文件
class FileLogger implements ILogger{
    public void log(String msg){
        DataOutputStream dos = null;
        try{
            dos = new DataOutputStream(new FileOutputStream("/home/lpp/tmp/log.txt", true));
            dos.writeBytes(msg + "\n");
            dos.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

//抽象类Decorator,实现了接口ILogger
//实现接口的原因:尽管需求分析变化了,但不管怎么变,它终究还是一个日志类。所以Decorator要派生自接口ILogger
abstract class Decorator implements ILogger{
    protected ILogger logger;
    public Decorator(ILogger logger){
        this.logger = logger;
    }
}

//子类Uplogger,用于将日志信息包装成大写的
class UpLogger extends Decorator{
    public UpLogger(ILogger logger){
        super(logger);
    }
    public void log(String msg){
        msg = msg.toUpperCase();    //覆写log方法。在当中添加对应的包装语句
        logger.log(msg);
    }
}

//子类XMLLogger,用于将日志信息包装成html格式写入日志文件
class XMLLogger extends Decorator{
    public XMLLogger(ILogger logger){
        super(logger);
    }
    public void log(String msg){
        String s = "<msg>\n" +
            "<content>" + msg + "</content>\n" +
            "<time>" + new Date().toString() + "</time>\n" +
            "</msg>\n";
        logger.log(s);
    }
}

//主类Test
public class Test{
    public static void main(String[] args) throws Exception{
        //        ILogger obj = new FileLogger();   //新建一个FileLogger对象
        ILogger obj = new ConsoleLogger();          //新建一个ConsoleLogger对象
        ILogger newObj = new XMLLogger(obj);        //将对象包装一下
        // ILogger newObj = new UpLogger(obj);      //包装对象
        String s[] = {"how", "are", "you"};         //待处理的信息
        for(int i = 0; i < s.length; i++){
            newObj.log(s[i]);       //调用包装后的对象,输出包装后的信息到对应位置
            Thread.sleep(1000);
        }
        System.out.println("End");
    }
}

通过包装,再进行添加了特定功能的特定输出就会变得很easy。

posted @ 2017-07-13 10:52  yfceshi  阅读(163)  评论(0编辑  收藏  举报