Java结构性设计模式中的装饰器模式介绍使用

作者:丨Jack_Chen丨 时间:2022-04-08 06:30:00 

装饰器模式

概述

装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),属于结构型模式。

它是指在不改变原有对象的基础之上,允许向一个现有的对象添加新的功能,同时又不改变其结构,作为现有的类的一个包装。

这种模式创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

提供了比继承更有单性的替代方案,进行扩展原有对象的功能。

装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态地扩展类的功能。

装饰器模式主要用于诱明且动态地扩展类的功能。

实现原理

让装饰器实现被包装类相同的接口,使得装饰器与被扩展类类型一致,并在构造函数中传入该接口对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能。

由于装饰器与被包装类属于同一类型,且构造函数的参数为其实现接口类,因此装饰器模式具备嵌套扩展功能,因此就能使用装饰器模式一层层的对最底层被包装类进行功能扩展。

在JDK中,IO相关包下大量使用装饰器模式,如BufferedReader、InputStream、OutputStream等类

主要角色

装饰器模式主要包含4种角色

1.抽象组件(Component)

抽象组件可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为。

2.具体组件(ConcreteComponent)

具体组件实现/继承抽象组件的一个具体对象,即被装饰对象。

3.抽象装饰器(Decorator)

通用的装饰具体组件的装饰器,其内部必然有一个属性指向抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个抽象组件,这是强制的通用行为。

如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么可以直接省略该类,而直接实现一个具体装饰器即可。

4.具体装饰器(ConcreteDecorator)

抽象装饰器的具体实现类,理论上,每个具体组件都扩展了抽象组件对象的一种功能。

应用场景

1.用于扩展一个类的功能或给一个类添加附加职责。

2.动态的给一个对象添加功能,这些功能可以再动态的澈销。

3.需要为一批的兄弟类进行改装或加装功能。

优缺点

优点:

1.装饰器是继承的补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。

2.装饰器完全遵守开闭原则。

缺点:

1.会出现更多的代码,更多的类,增加程序复杂性。

2.通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。

3.动态装饰时,多层装饰时会更复杂。

装饰器模式的基本使用

创建抽象组件

创建Phone抽象类

public abstract class Phone {
   public abstract String call();
   public abstract double price();
}

具体组件

创建最基本具有打电话功能的手机

public class BasePhone extends Phone {
   @Override
   public String call() {
    return "BasePhone call";
   }
   @Override
   public double price() {
       return 0.1;
   }
}

抽象装饰器

创建一个抽象装饰器来扩展该只具备基本功能的手机

public abstract class PhoneDecorator extends Phone {
   private Phone phone;
   public PhoneDecorator(Phone phone) {
       this.phone = phone;
   }
   @Override
   public String call() {
       return phone.call();
   }
   @Override
   public double price() {
       return phone.price();
   }
   /**
    * 扩展功能
    */
   public abstract void sendMsg();
}

具体装饰器

public class SatellitePhoneDecorator extends PhoneDecorator{
   public SatellitePhoneDecorator(Phone phone) {
       super(phone);
   }
   public void sendMsg() {
       System.out.println("PhoneCallDecorator sendMsg");
   }
   @Override
   public String call() {
       return  "SatellitePhone call";
   }
   @Override
   public double price() {
       return super.price()+100;
   }
}

客户端调用

public static void main(String[] args) {
       // 创建需要被装饰的原始对象(即要被装饰的对象)
       Phone phone = new BasePhone();
       System.out.println("使用: "+phone.call()+" 方式打电话,每分钟单价:" + phone.price());
       // 给对象透明的增加额外功能并调用
       PhoneDecorator phoneDecorator = new SatellitePhoneDecorator(phone);
       System.out.println("使用: "+phoneDecorator.call()+" 方式打电话,每分钟单价:" + phoneDecorator.price());
       // 装饰器也可以装饰具体的装饰对象,相当于给对象在增加的功能基础上在添加功能,这里体现在单价100.1基础上再+100
       PhoneDecorator satellitePhoneDecorator = new SatellitePhoneDecorator(phoneDecorator);
       System.out.println("使用: "+satellitePhoneDecorator.call()+" 方式打电话,每分钟单价:" + satellitePhoneDecorator.price());
       satellitePhoneDecorator.sendMsg();
   }

使用: BasePhone call 方式打电话,每分钟单价:0.1
使用: SatellitePhone call 方式打电话,每分钟单价:100.1
使用: SatellitePhone call 方式打电话,每分钟单价:200.1
PhoneCallDecorator sendMsg

来源:https://blog.csdn.net/qq_38628046/article/details/126131404

标签:Java,装饰器模式,设计模式
0
投稿

猜你喜欢

  • 如何在IDEA Maven项目中导入本地jar包的步骤

    2023-03-25 06:43:48
  • Java基本语法之内部类示例详解

    2023-02-06 14:05:32
  • Android画板开发之基本画笔功能

    2023-01-09 07:26:21
  • 简单工厂模式_动力节点Java学院整理

    2022-07-22 16:42:08
  • Java基础学习之集合底层原理

    2023-09-30 22:16:40
  • 基于javaWeb 项目SSM配置要点及可能遇到的问题和解决方法

    2023-10-27 21:45:16
  • 详解C# Socket异步通信实例

    2022-08-27 14:27:22
  • Java使用Apache.POI中HSSFWorkbook导出到Excel的实现方法

    2022-05-24 17:14:13
  • C#中的多线程多参数传递详解

    2023-08-02 22:23:46
  • Mybatis下的SQL注入漏洞原理及防护方法解析

    2022-06-30 18:38:29
  • springcloud使用feign调用服务时参数内容过大问题

    2022-08-31 11:23:26
  • C#中三种Timer计时器的详细用法

    2022-12-14 13:52:34
  • 关于SpringSecurity配置403权限访问页面的完整代码

    2023-11-13 02:03:59
  • JVM内存增强之逃逸分析

    2022-01-23 00:22:08
  • IDEA 快速返回上次查看代码的位置的方法

    2022-10-23 01:49:59
  • Android 6.0动态权限申请教程

    2023-09-26 16:43:56
  • spring框架集成flyway项目的详细过程

    2023-09-14 11:47:14
  • java中数组的定义及使用方法(推荐)

    2022-03-07 14:20:16
  • Java SQL注入案例教程及html基础入门

    2023-09-22 08:34:12
  • SpringBoot实现单文件上传

    2023-10-01 21:43:42
  • asp之家 软件编程 m.aspxhome.com