当前位置:   article > 正文

23种设计模式——装饰者模式

装饰者模式

23种设计模式——装饰者模式

1、装饰者模式概述

背景

有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。

装饰者模式的定义

装饰者(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。

装饰者模式属于对象结构型模式,也体现了开闭原则(ocp)。

装饰者模式的优缺点

优点

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

缺点:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。

2、装饰者模式的结构

装饰者模式的结构

装饰器模式主要包含以下角色。

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

装饰者模式的结构图

在这里插入图片描述

3、装饰者模式的实现

实现星巴克咖啡+调味品的下单,并计算费用

定义抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。

public abstract class Drink {

    public String dsc; //描述
    private float price = 0.0f; //价格

    public String getDsc() {
        return dsc;
    }

    public void setDsc(String dsc) {
        this.dsc = dsc;
    }

    public float getPrice() {
        return price;
    }

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

    //计算费用的抽象方法,由子类实现
    public abstract float cost();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

定义具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。

public class Coffee extends Drink{
    @Override
    public float cost() {
        return super.getPrice();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

具体构件(ConcreteComponent)角色1:Espresso 意大利咖啡

public class Espresso extends Coffee{

    public Espresso(){
        setDsc("意大利咖啡");
        setPrice(10.0f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

具体构件(ConcreteComponent)角色2:LongBlack 美式咖啡1

public class LongBlack extends Coffee{
    
    public LongBlack(){
        setDsc("美式咖啡1");
        setPrice(9.0f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

具体构件(ConcreteComponent)角色3:LongBlack 美式咖啡2

public class ShortBlack extends Coffee{
    
    public ShortBlack(){
        setDsc("美式咖啡2");
        setPrice(8.0f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

定义抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

public class Decorator extends Drink{

    //装饰者组合了抽象构件(被装饰者)
    private Drink obj;

    public Decorator(Drink obj){
        this.obj = obj;
    }

    @Override
    public float cost() {
        //计算费用:父类的费用 + 自己的费用
        return getPrice() + obj.getPrice();
    }

    @Override
    public String getDsc() {
        //输出描述:父类的描述 + 自己的描述
        return dsc + " " + getPrice() + " " +obj.getDsc();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

定义具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

具体装饰(ConcreteDecorator)角色1:巧克力 Chocolate

public class Chocolate extends Decorator{

    public Chocolate(Drink obj) {
        super(obj);
        setDsc("巧克力");
        setPrice(3.0f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

具体装饰(ConcreteDecorator)角色2:牛奶 Milk

public class Milk extends Decorator{
    
    public Milk(Drink obj) {
        super(obj);
        setDsc("牛奶");
        setPrice(2.0f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

具体装饰(ConcreteDecorator)角色3:豆浆 Soy

public class Soy extends Decorator{
    
    public Soy(Drink obj) {
        super(obj);
        setDsc("豆浆");
        setPrice(1.5f);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

编写测试类下咖啡订单,测试装饰者模式:

public class coffeeBar {
    public static void main(String[] args) {

        //一杯美式
        Drink order1 = new LongBlack();
        System.out.println("订单描述:" + order1.getDsc());
        System.out.println("订单费用= " + order1.cost());

        //一杯美式 + 一份牛奶
        order1 = new Milk(order1);
        System.out.println("订单描述:" + order1.getDsc());
        System.out.println("订单费用= " + order1.cost());

        //一杯美式 + 2份牛奶
        order1 = new Milk(order1);
        System.out.println("订单描述:" + order1.getDsc());
        System.out.println("订单费用= " + order1.cost());

        //一杯美式 + 2份牛奶 + 巧克力
        order1 = new Chocolate(order1);
        System.out.println("订单描述:" + order1.getDsc());
        System.out.println("订单费用= " + order1.cost());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

4、装饰者模式的应用场景

装饰者模式的应用场景

  • 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现。
  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

装饰器模式在 Java 中的体现

装饰器模式在 Java语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/552010
推荐阅读
相关标签
  

闽ICP备14008679号