《设计模式入门》 8.装饰器模式

装饰器模式主要用于对象的功能扩展。我们使用装饰类动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。装饰器的核心就是再不改原有类的基础上给类新增功能,并且不改变原有类。

        一般我们提到对象功能扩展,很大一部分都会联想到使用继承,或者AOP的方式。我们使用装饰器模式来设计程序,不仅能避免AOP的复杂,还能解决继承不断横向扩展导致子类膨胀的问题,我们不在考虑大量子类的维护了。

装饰模式一共有四部分组成:

  1. 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
  2. 具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
  3. 抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
  4. 具体装饰器角色(ConcreteDecorator):向组件添加职责。

=========================================================================

我们模拟一个往主板装硬件的过程:

        我们再一个主板上装载内存,显卡等硬件,并且打印总价以及配件单。

首先定义一个硬件的超类,所有的不论是主板还是显卡,内存都属于硬件。也就是抽象组件角色

package DecoratorPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Computer.java
 * @Description 电脑类,超类
 * @createTime 2022年03月01日 17:28:00
 */
public abstract class HardWare {
    protected String name;

    private BigDecimal price;

    public String getName() {
        return name;
    }

    public void setHardWareList(String name) {
        this.name = name;
    }

    public BigDecimal getPrice()
    {
        return price;
    }

    public void setPrice(BigDecimal price)
    {
        this.price=price;
    }

    /**
     * 获取总价
     * @return 价格
     */
    public abstract BigDecimal cost();

    /**
     * 获取配置单
     * @return 配置单
     */
    public abstract String hardWareList();
}

然后定义一个主板类,将会被其他硬件修饰的主体,也就是具体组件角色

package DecoratorPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName DellComputer.java
 * @Description 主板类
 * @createTime 2022年03月02日 08:38:00
 */
public class MotherBoard extends  HardWare {
    @Override
    public BigDecimal cost() {
        return super.getPrice();
    }

    @Override
    public String hardWareList() {
        return super.getName();
    }
}

然后构建一个抽象装饰器,所有的装饰类都要被这个类所规范

package DecoratorPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Decorator.java
 * @Description 硬件装饰类
 * @createTime 2022年03月02日 09:36:00
 */
public class Decorator extends HardWare{
    private  HardWare obj;
    
    public Decorator( HardWare obj){
        this.obj = obj;
    }

    /**
     * 生成总价
     * @return 总价
     */
    @Override
    public BigDecimal cost() {
        return super.getPrice().add(obj.cost());
    }

    /**
     * 生成配件表
     * @return 配件表
     */
    @Override
    public String hardWareList() {
        return super.getName()+"\n"+obj.name;
    }
}

然后添加两个具体装饰器角色,也就是我们即将放上主板的内存和显卡:

显卡:

package DecoratorPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName GraphicCard.java
 * @Description 显卡装饰
 * @createTime 2022年03月02日 10:07:00
 */
public class GraphicCard extends Decorator{
    public GraphicCard(HardWare obj) {
        super(obj);
        super.setHardWareList("ROC 3090");
        super.setPrice(BigDecimal.valueOf(12999));
    }
}

内存:

package DecoratorPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Memory.java
 * @Description 内存装饰
 * @createTime 2022年03月02日 09:46:00
 */
public class Memory extends Decorator{
    public Memory(HardWare obj) {
        super(obj);

        super.setHardWareList("TridentZ Royal");;

        super.setPrice(BigDecimal.valueOf(3200));
    }
}

测试一下:

package DecoratorPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Computer.java
 * @Description 打印配置单
 * @createTime 2022年03月02日 09:47:00
 */
public class Computer {
    public static void main(String[] args) {

        HardWare list;

        list = new ROGSTRIXZ690();
        System.out.println("主板价格: "+list.getPrice());

        list = new Memory(list);
        System.out.println("内存价格: "+list.getPrice() );

        list = new GraphicCard(list);
        System.out.println("显卡价格: "+list.getPrice());

        System.out.println("总价:"+list.cost());
        System.out.println("配件单: \n"+list.hardWareList());

    }
}

优点:

  1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  2. 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
  3. 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

缺点:

  1. 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
  2. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

PigeonEssence

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值