【设计模式】第12章·装饰模式

本文介绍了装饰模式,一种用于动态给对象添加职责的设计模式。通过实例展示了如何使用装饰模式来扩展手机接收到来电时的功能,从仅有声音提醒到加入震动和灯光闪烁提示。装饰模式提供了比继承更灵活的扩展方式,允许在不修改原有代码的情况下增加新功能,遵循开闭原则。然而,它也可能导致大量小对象的产生,增加调试难度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、装饰模式概述

装饰模式:用于动态地给一个对象增加一些额外的职责。
就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案,它是一种对象结构型模式。

二、装饰模式结构与实现

2.1 装饰模式结构

包含4个角色:
1,Component(抽象构件):是具体构件类和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法;
2,ConcreteComponent(具体构件):实;了在抽象构件中声明的方法,装饰类可以给他增加额外的职责。
3,Decorator(抽象装饰类):用于给具体构件增加职责,但是具体职责在其子类中实现;
4,ConcreteDecorator(具体装饰类):负责向构件中添加新的职责。

2.2 装饰模式实现

//充当抽象构件的角色

/**
 * 抽象构建类
 */
public abstract class Phone {

    /**
     * 接收来电的方法
     */
    public abstract void incomingTelegram();

}

//充当具体构件的角色

/**
 * 具体构件类
 */
public class HuaweiPhone extends Phone {

    @Override
    public void incomingTelegram() {
        System.out.println("来电时发出声音提醒");
    }
}

//充当抽象装饰类的角色

/**
 * 抽象装饰类
 */
public class PhoneDecorator extends Phone {

    Phone phone;

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

    @Override
    public void incomingTelegram() {
        phone.incomingTelegram();
    }

}

//充当具体装饰类的角色

/**
 * 具体装饰类
 */
public class JarPhoneDecorator extends PhoneDecorator{

    public JarPhoneDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public void incomingTelegram() {
        addJar();
        super.incomingTelegram();
    }

    public void addJar() {
        System.out.println("来电时发出震动");
    }

}

/**
 * 具体装饰类
 */
public class FlickeringPhoneDecorator extends PhoneDecorator{

    public FlickeringPhoneDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public void incomingTelegram() {
        addFlickering();
        super.incomingTelegram();
    }

    public void addFlickering() {
        System.out.println("来电时有灯光闪烁提示");
    }
}

//客户端

public class Client {

    public static void main(String[] args) {

        /**
         * 案例需求描述:
         * 最简单的手机在接收到来电时候会发出声音提醒主人,
         * 现在需要为该手机添加一项功能,
         * 在接收来电时除了有声音还能产生震动;
         * 或者来电时不仅能够发声,产生震动,而且还有灯光闪烁提示。
         * 试用装饰模式来模式手机功能升级的过程。
         *
         */

        Phone p1, p2, p3;

        p1 = new HuaweiPhone();
        p2 = new JarPhoneDecorator(p1);
        p3 = new FlickeringPhoneDecorator(p2);
        p1.incomingTelegram();
        System.out.println("------");
        p2.incomingTelegram();
        System.out.println("------");
        p3.incomingTelegram();
    }
}

三、装饰模式的优缺点和适用环境

3.1 装饰模式的优点

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

3.2 装饰模式的缺点

  1. 使用装饰模式进行系统设计时将产生很多小对象;
  2. 装饰模式比继承更加易于出错,排错也更加困难,对于多次装饰的对象,在调试时寻找错误可能需要逐级排查,较为繁琐。

3.3 装饰模式的适用环境

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

【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。

【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值