装饰器模式

概述

装饰器模式(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

到此这篇关于Java结构性设计模式中的装饰器模式介绍使用的文章就介绍到这了,更多相关Java装饰器模式内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Java结构性设计模式中的装饰器模式介绍使用的更多相关文章

  1. MVVM 不是那么好

    我觉得MVVM是一种反人类的设计模式,它使架构更加混乱而非清晰。MVVM命名很糟糕名称是很重要的。ViewModel这一名称则没有发挥任何作用。ViewModel的第一种含义是modelfortheview。MVVM引进太多职责命名不够具体,导致这个类的任务无休止地增长。MVVM不改变你的架构viewmodel并不能从根本上改变你的应用程序的架构。我能想到的MVVM模式最大的好处就是它把“下水道”从苹果自带的viewcontrooller类转移到了viewmodel这一自定义的对象。

  2. 开发Swift iOS应用程序“正确的方式”

    最近,我学习了Swift和开发iOS应用程序的基础知识。现在,我想自己开发一个真正的应用程序,但我非常关心编写好的代码,所以我已经寻找“最佳实践”,“设计模式”和“正确的方式”来实现它。在我的搜索中,我发现这个greattutorial关于SwiftiOS应用程序中通常使用的所有设计模式,以及他们使用的示例。不应该将httpClient和persistencyManager声明为协议,然后HttpClient和PersistencyManager类实现该协议?我应该在哪里告诉应用程序?最后但并非最不重要的

  3. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. javascript的23种设计模式示例总结大全

    这篇文章主要为大家介绍了javascript的23种设计模式的总结大全,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  7. 详解JavaScript实现设计模式中的适配器模式的方法

    适配器模式可以根据需求转换(或调整)一个接口,创建含有您所需接口的另一个对象,并将它连接到您想改变接口的对象,从而完成这种转换,下面就来详解JavaScript实现设计模式中的适配器模式的方法

  8. Java实现世界上最快的排序算法Timsort的示例代码

    Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。本文将详解Timsort算法是定义与实现,需要的可以参考一下

  9. PHP设计模式之工厂模式详解

    这篇文章主要为大家详细介绍了PHP设计模式之工厂模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Java日期工具类的封装详解

    在日常的开发中,我们难免会对日期格式化,对日期进行计算,对日期进行校验,为了避免重复写这些琐碎的逻辑,我这里封装了一个日期工具类,方便以后使用,直接复制代码到项目中即可使用,需要的可以参考一下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部