Java装饰器模式详解

前言

装饰器模式也叫做包装器模式,属于结构性设计模式一种,装饰器设计模式在实际的生活中也有很多体现,举例来说,某手机厂商发布了XXX标准版手机,为了吸引用户眼球,提升销量,还特别有纪念碑,青春版,至尊版等

我们可以这么设想,不管是哪个版本的手机,其基本的功能是不变的,电话、短信、拍照等这些基础的功能在各个版本都能找到

但是不同的版本,基于某个基础的版本,根据标价的不同添加了更多定制化或个性化的功能,相当于是说丰富了标准版的功能

  • 装饰器模式作为现有类的一个包装,允许向现有的对象添加注入新的功能,同时还不改变原有的结构
  • 给基础对象添加功能,一般有2种方式,继承或关联组合,将一个类的对象嵌入到另一个对象中,由另一个对象来决定是否调用嵌入对象的行为来增强功能,这个就是装饰器模式,相比继承更加灵活

在JDK源码里面使用最多的就是IO流,大量使用到了装饰器设计模式

装饰器设计模式的简易结构图如下所示:
在这里插入图片描述

对上图中各个组件的作用做简单的解释:

  • 角色:(装饰者和被装饰者具有相同的超类(可以理解为接口))
  • 抽象组件:定义装饰器方法的规范,比如手机,仅定义了打电话,发短信功能
  • 被装饰者:Component的具体实现,也就是我们即将要装饰的具体对象,实现了接口中的方法,比如打电话,发短信
  • 装饰者组件:定义了具体装饰者的行为规范,和Component角色具有相同的接口,并持有组件(Component)对象实例的引用,即其他版本的手机都有打电话和短信的功能
  • 具体装饰物:负责给基础组件添加新的功能,比如在电话和短信基础上定制了视频通话功能

代码演示

定义基本的接口

public interface Phone {
    String desc();
    int getPrice();
}

具体的被装饰类的实现,以手机为例,这里提供标准版手机,普通版和高配版

StandardPhone

public class StandardPhone implements Phone{

    private String desc = "标准版手机";

    @Override
    public String desc() {
        return desc;
    }

    @Override
    public int getPrice() {
        return 1000;
    }

}

MiddlePhone

public class MiddlePhone implements Phone{

    private String desc = "普通版手机";

    @Override
    public String desc() {
        return desc;
    }

    @Override
    public int getPrice() {
        return 1500;
    }
}

HighLevelPhone

public class HighLevelPhone implements Phone{

    private String desc = "尊贵版手机";

    @Override
    public String desc() {
        return desc;
    }

    @Override
    public int getPrice() {
        return 2500;
    }
}

手机装饰器:

装饰器在这里起到一个中间层作用,方便后面的扩展,具体的装饰实现延迟到子类中

public class PhoneDecorator implements Phone {

    private String desc = "这是装饰器";

    @Override
    public String desc() {
        return desc;
    }

    @Override
    public int getPrice() {
        return 0;
    }

}

添加了视频通话的装饰器类

public class VideoDecorator extends PhoneDecorator{

    private String desc = "增加一个视频通话功能";

    private int videoPrice = 500;

    private Phone phone;

    public VideoDecorator(Phone phone){
        this.phone=phone;
    }

    @Override
    public String desc() {
        return phone.desc() + "," + desc;
    }

    @Override
    public int getPrice() {
        return phone.getPrice() + videoPrice;
    }

}

增加了wifi充电功能的装饰器类

public class WifiChargeDecorator extends PhoneDecorator {

    private String desc = "增加一个wifi充电功能";

    private int wifiAddProce = 800;

    private Phone phone;

    public WifiChargeDecorator(Phone phone){
        this.phone=phone;
    }

    @Override
    public String desc() {
        return phone.desc() + "," + desc;
    }

    @Override
    public int getPrice() {
        return phone.getPrice() + wifiAddProce;
    }
}

新增的手机的附加功能可以通过多个装饰类实现,方便客户端调用时自由选择,如果有更多的装饰类,可以按照上面的方式继续添加

下面来简单测试下,

1、获取一个普通版手机

public static void main(String[] args) {
        /**
         * 基础测试
         */
        Phone phone = new MiddlePhone();
        System.out.println(phone.desc() + " --- " + phone.getPrice());
    }

在这里插入图片描述

2、在普通版手机基础上增加视频通话功能

public static void main(String[] args) {
        /**
         * 基础测试
         */
        Phone phone = new MiddlePhone();
        System.out.println(phone.desc() + " --- " + phone.getPrice());
        System.out.println();
        /**
         * 增加视频通话功能
         */
        phone = new VideoDecorator(phone);
        System.out.println(phone.desc() + " --- " + phone.getPrice());
    }

在这里插入图片描述
3、在普通版手机基础上继续增加wifi充电功能

public static void main(String[] args) {
        /**
         * 基础测试
         */
        Phone phone = new MiddlePhone();
        System.out.println(phone.desc() + " --- " + phone.getPrice());
        System.out.println();
        /**
         * 增加视频通话功能
         */
        phone = new VideoDecorator(phone);
        System.out.println(phone.desc() + " --- " + phone.getPrice());
        System.out.println();

        /**
         * 增加wifi充电功能
         */
        phone = new WifiChargeDecorator(phone);
        System.out.println(phone.desc() + " --- " + phone.getPrice());
    }

在这里插入图片描述

通过上面的代码演示,可以清楚的看到,使用装饰器模式可以很灵活的对既有的基础组件对象持有的功能进行补充和扩展,可以根据自身的业务诉求进行自由搭配

装饰器设计模式,优点:

  • 装饰模式与继承关系的目的都是要扩展原有对象的功能,但是装饰器模式比继承增加了更多的灵活性
  • 使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出更多的不同行为的组合,原有的代码无需改变,符合“开闭”原则

缺点:

  • 装饰器模式添加了许多子类,过多使用会使程序变得很复杂
  • 增加了系统的复杂程度,加大了使用者的学习成本和理解难度

在JDK源码中的应用

IO流的读取与写入在JDK源码中大量使用到了装饰器模式,简单来说,按照装饰器模式下其组件的划分,可以总结如下:

  • 抽象组件:(Component):Inputstream,定义了装饰方法的规范
  • 被装饰者:(ConcreteComponent):FileInputStream,ByteArrayInputStream,Component的具体实现,也就是要装饰的具体对象
  • 装饰者组件:(Decorator):FileInputStream,定义装饰者行为规范,和Component具有相同接口,持有对象组件(Component)的实例引用
  • 具体装饰物:(ConcreteDecorator)BufferedInputStream,DataInputStream,负责给构件对象添加额外的功能

下面来看一下DataInputStream和DataOutputStream的类结构图,可以发现它们的顶层实现了InputStream或者OutputStream
在这里插入图片描述

在这里插入图片描述

一个具体的实现案例

public static void main(String[] args) throws IOException {
        DataInputStream in = new DataInputStream(new FileInputStream("D:\\test.txt"));
        DataOutputStream out = new DataOutputStream(new FileOutputStream("D:\\test1.txt"));
        BufferedReader d = new BufferedReader(new InputStreamReader(in));
        String count;
        while ((count = d.readLine()) != null) {
            String u = count.toUpperCase();
            System.out.println(u);
            out.writeBytes(u + "  ,");
        }
        d.close();
        out.close();
    }

本篇通过实例演示并说明了装饰器设计模式的使用,可以结合自身的业务使用装饰器模式对代码进行优化和改进,本篇到此结束,最后感谢观看!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码农叔叔

谢谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值