IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 设计模式-装饰者模式 -> 正文阅读

[Java知识库]设计模式-装饰者模式

  装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

下面使用装饰器模式煎饼加码的问题

来看这样一个场景,上班族大多有睡懒觉的习惯,每天早上上班都时间很紧张,于是很多人为了多睡一会儿,就用更方便的方式解决早餐问题,有些人早餐可能会吃煎饼。煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么加码,都还是一个煎饼。再比如,给蛋糕加上一些水果,给房子装修,都是装饰器模式。

首先创建一个煎饼抽象类 Battercake 代码如下:

public abstract class Battercake {

    protected abstract String getMsg();

    protected abstract double getPrice();
}

创建煎饼基础套餐类(BaseBattercake)继承煎饼抽象类 代码如下:

public class BaseBattercake extends Battercake {
    @Override
    protected String getMsg() {
        return "煎饼";
    }

    @Override
    protected double getPrice() {
        return 5;
    }
}
创建煎饼基础套餐的扩展抽象装饰类(BattercakeDecorator) 代码如下:
public abstract class BattercakeDecorator extends Battercake{
    //静态代理,委派
    private Battercake battercake;

    public BattercakeDecorator(Battercake battercake){
        this.battercake = battercake;
    }

    @Override
    protected String getMsg() {
        return this.battercake.getMsg();
    }

    @Override
    protected double getPrice() {
        return this.battercake.getPrice();
    }
}

创建加鸡蛋套餐的装饰器类(EggDecorator)

public class EggDecorator extends BattercakeDecorator {

    public EggDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    protected String getMsg() {
        return super.getMsg() + "+1个鸡蛋";
    }

    @Override
    protected double getPrice() {
        return super.getPrice()+1;
    }
}

创建加香肠套餐的装饰器类(SausageDecorator)

public class SausageDecorator extends BattercakeDecorator{
    public SausageDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    protected String getMsg() {
        return super.getMsg()+"+1个香肠";
    }

    @Override
    protected double getPrice() {
        return super.getPrice() + 2;
    }
}

测试代码如下:

public class DecoratorTest {

    public static void main(String[] args) {
        Battercake battercake = null;
        //煎饼
        battercake = new BaseBattercake();
        System.out.println(battercake.getMsg()+ "  总收费:"+battercake.getPrice()+"元");
        //加1个鸡蛋
        battercake = new EggDecorator(battercake);
        System.out.println(battercake.getMsg()+ "  总收费:"+battercake.getPrice()+"元");
        //加1个鸡蛋
        battercake  = new EggDecorator(battercake);
        System.out.println(battercake.getMsg()+ "  总收费:"+battercake.getPrice()+"元");
        //加1个香肠
        battercake = new SausageDecorator(battercake);

        System.out.println(battercake.getMsg()+ "  总收费:"+battercake.getPrice()+"元");
    }
}

测试结果如下:

与静态代理的最大区别就是职责不同,静态代理注重于功能增强,装饰器更多考虑的是扩展

项目中用到的日志修饰场景 ,假如要把logger日志的输出内容以json的形式输出

未修饰之前的代码如下:

public class JsonLoggerTest {

    private static final Logger logger = LoggerFactory.getLogger(JsonLoggerTest.class);
//    private static final Logger logger = JsonLoggerFactory.getLogger(JsonLoggerTest.class);

    public static void main(String[] args) {
        logger.error("错误!");
    }
}

结果如下:

过程首先要创建一个Logger的修饰器类(DecoratorLogger) 代码如下:

public class DecoratorLogger implements Logger {

    public Logger logger;

    public DecoratorLogger(Logger logger){
        this.logger = logger;
    }


    public void error(String s) {

    }

    public void error(String s, Object o) {

    }

    @Override
    public void error(String s, Object o, Object o1) {

    }

    ...后面方法省略
}

创建具体组件 JsonLogger 代码如下:

public class JsonLogger extends DecoratorLogger {
    public JsonLogger(Logger logger) {
        super(logger);
    }

    @Override
    public void info(String msg){
        JSONObject jsonResult = composeBasicJsonResult();
        jsonResult.put("Exception",msg);
        logger.info(jsonResult.toJSONString());
    }

    @Override
    public void error(String msg){
        JSONObject jsonResult = composeBasicJsonResult();
        jsonResult.put("Exception",msg);
        logger.error(jsonResult.toJSONString());
    }

    public void error(Exception e){
        JSONObject jsonResult = composeBasicJsonResult();
        jsonResult.put("Exception",e);
        logger.error(jsonResult.toJSONString());
    }

    private JSONObject composeBasicJsonResult() {
        //拼装了一些运行时的信息
        return new JSONObject();
    }

}

可以看到,在JsonLogger中,对于Logger的各种接口,我们都用JsonObject对象进行一层封装。在打印的时候,最终还是调用原生接口logger.error(string),只是这个String参数已经被装饰过了。如果有额外的需求,则可以再写一个函数去实现。比如error(Exception e),只传入一个异常对象,这样在调用时就非常方便。另外,为了在新老交替的过程中尽量不改变太多代码和使用方式,笔者又在JsonLogger中加入了一个内部的工厂类JsonLoggerFactory(这个类转移到DecoratorLogger中可能更好一些)。它包含一个静态方法,用于提供对应的JsonLogger实例。最终在新的日志体系中。

JsonLoggerFactory 工厂类代码:

public class JsonLoggerFactory {

    public static JsonLogger getLogger(Class<?> clazz){
        return new JsonLogger(LoggerFactory.getLogger(clazz));
    }
}

??使用修饰后的代码如下:

public class JsonLoggerTest {

//    private static final Logger logger = LoggerFactory.getLogger(JsonLoggerTest.class);
    private static final Logger logger = JsonLoggerFactory.getLogger(JsonLoggerTest.class);

    public static void main(String[] args) {
        logger.error("错误!");
    }
}

?结果如下:

?

参考:

趣谈装饰器模式,让你一辈子不会忘

设计模式之装饰者模式 - 心中的山水 - 博客园

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:21:19  更:2022-03-24 00:22:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:49:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码