装饰模式-扩展系统功能

news/2024/7/5 3:32:10

 买了新车后,不少人会对车进行装饰,比如给车贴膜,喷上骚粉的漆等。某天,小李和小张都买了辆车,小李想给车贴膜,小张想给车先喷漆然后再贴膜。现在中的做法是,把车开到改装店,如果要喷漆,师傅就给车喷漆,要贴膜,师傅就给车贴膜。这就是本文要将的装饰模式。

1 装饰模式概述

是一种替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。引入装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。

图 装饰模式结构图

Component: 抽象构件,是具体构件和抽象装饰类的共同父类。它的引入使得客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

ConcreteComponent:具体构件,抽象构件类的子类。用于定义具体的构件对象,装饰器可以给它增加额外的职责(方法)。

Decorator: 抽象装饰类,也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。维护了一个指向抽象构件对象的引入,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

ConcreteDecorator: 具体装饰类,负责向构件添加新的职责。每个具体装饰类都定义了一些新的行为,可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

public interface Appearance {

    void show();

}

public class Car implements Appearance{

    private String name;

    public Car(String name) {
        this.name = name;
    }

    @Override
    public void show() {
        System.out.println(name + ":");
    }
}

public class Decorator implements Appearance{

    private Appearance appearance;

    public void setAppearance(Appearance appearance) {
        this.appearance = appearance;
    }

    @Override
    public void show() {
        appearance.show();
    }
}

public class FilmDecorator extends Decorator{

    @Override
    public void show() {
        super.show();
        attachFilm();
    }

    private void attachFilm() {
        System.out.println("贴上一层保护膜");
    }
}

public class PaintDecorator extends Decorator{

    @Override
    public void show() {
        super.show();
        spray();
    }
    private void spray() {
        System.out.println("喷上骚粉色");
    }
}

public class CarTuningShop {

    public static void main(String[] args) {
        Appearance car1 = new Car("小李的车");
        Appearance car2 = new Car("小张的车");

        Decorator filmDec = new FilmDecorator(); //贴膜
        Decorator paintDec = new PaintDecorator(); //喷漆

        filmDec.setAppearance(car1);
        filmDec.show();
        System.out.println("--------");
        filmDec.setAppearance(car2);
        paintDec.setAppearance(filmDec);
        paintDec.show();
//        运行结果:
//        小李的车:
//        贴上一层保护膜
//        --------
//        小张的车:
//        贴上一层保护膜
//        喷上骚粉色
    }

}

1.1 透明装饰模式

要求客户端完全针对抽象编程,对于客户端而言,具体构件对象和具体装饰对象没有任何区别。

优点:可以让客户端透明地使用装饰之前的对象和装饰之后的对象,无须关心它们的区别。

缺点:设计难度较大,有时用户需要单独调用新增的业务方法或者是抽象装饰器的方法,这样就不得不用具体装饰类来定义装饰之后的对象。

1.2 半透明装饰模式

对于客户端,区分了具体装饰对象和构件对象。因为客户端要单独使用装饰器的业务方法,就用具体的装饰类来定义装饰之后的对象。而具体构建类型还是可以使用抽象构件类型来定义,这种装饰模式即为半透明装饰模式。

优点:给系统代理更多的灵活性,设计及使用相对简单。

缺点:客户端需要有区别地对待具体构件与装饰类,

1.3 注意事项

1)尽量保持装饰类的接口与被装饰类的接口相同。这样,对于客户端而言,可以一致地对待它们。也就是说,在可能的情况下,应该尽量使用透明装饰模式。

2)尽量保持具体构件类ConcreteComponent是一个“轻”类。不要把太多的行为放在具体构件类中,可以通过装饰类对其进行扩展。

3)如果只有一个具体构件类,那么抽象装饰类可以作为该具体构件类的直接子类。

2 优缺点

优点:

  1. 比继承更加灵活,不会导致类的个数急剧增加。
  2. 可以通过一种动态的方式来扩展一个对象的功能。
  3. 可以对一个对象进行多次装饰,使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有代码无须改变,符合开闭原则。

缺点:

  1. 将产生很多小对象,会占用更多的系统资源。
  2. 比继承更容易出错,排错也更困难,需要逐级排查。

3 适用场景

  1. 不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  2. 不能采用继承的方式对系统进行扩展或者继承不利于系统扩展和维护。

http://lihuaxi.xjx100.cn/news/1372162.html

相关文章

【测试笔记】示波器的使用示例(多图形说明,少文字描述)

示波器的使用示例 一、示波器图样二、总体介绍三、分布介绍3.1 分段线设置3.2 单通道波形调整3.3 整体波形图像调整3.4 滚动模式3.5 测量显示选择3.6 储存选择3.7 触发捕获模式选择 前言:本篇文章是我使用示波器后的一个功能记录,多为常用功能记录&#…

七大设计模式原则

1、开闭原则(Open-closed Principle) 开闭原则,是面向设计中最基础的设计原则。 一个软件实体类、模块、函数应该对扩展开放、对修改关闭。 强调的是用抽象构建框架,用实现扩展细节。可以提高软件系统的可复用性和可维护性。 实…

Promise基础

Promise对象 Promise概念 Promise 对象表示异步操作最终的完成(或失败)以及其结果值。 一个 Promise 是一个代理,它代表一个在创建 promise 时不一定已知的值。它允许你将处理程序与异步操作的最终成功值或失败原因关联起来。这使得异步方…

能耗监测管理系统

能耗监测管理系统是一种用于监测和管理能源消耗的软件系统,可以帮助企业、机构或个人实现对能源消耗的实时监控、分析和管理。随着能源问题的日益凸显,能耗监测管理系统的重要性也越来越受到人们的关注。本文将从以下几个方面介绍能耗监测管理系统。 一、…

Delta 表定时Compact设计

Delta 表定时Compact设计 目前我们的数仓中delta表实时跟离线的都有,离线的表主要是每天的定时任务的运行,并根据日期字段进行分区的存储。离线任务正常是读取前一天的数据计算,并写入当天的时间分区,或者是重跑数据,…

[leetcode]2365. Task Scheduler II

链接:力扣 给你一个下标从 0 开始的正整数数组 tasks ,表示需要 按顺序 完成的任务,其中 tasks[i] 表示第 i 件任务的 类型 。 同时给你一个正整数 space ,表示一个任务完成 后 ,另一个 相同 类型任务完成前需要间隔…

华纳云:Linux系统的SVN服务器怎么安装配置

在Linux系统上搭建SVN服务器,可以使用Apache HTTP Server作为SVN的前端服务器,并安装Subversion软件包用于管理版本库。下面是安装配置SVN服务器的基本步骤(以Ubuntu为例): 安装Apache HTTP Server和Subversion&#…

TCP实现原理和为什么需要三次握手?两次握手不可以?四次握手不可以?

TCP实现原理和为什么需要三次握手?两次握手不可以?四次握手不可以? 1. 什么是TCP协议? TCP:Transmission Control Protocol翻译过来就是传输控制协议,TCP协议是一个面向连接的、可靠的、基于字节流的传输层协议RFC 793对TCP连接的定义 > Connections: >…