设计模式十:装饰器(Decorator)

现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时为对象动态地添加额外的行为或功能,而无需修改原始类的代码。该模式通过创建一个包装器,即装饰器,来包裹原始对象,并以透明的方式扩展其功能。装饰器和原始对象都实现了相同的接口,这使得它们可以互相替代使用。

装饰器模式适用于以下场景:

装饰器模式适用于需要在运行时动态地扩展对象功能,以及对核心对象进行修改但又不希望直接修改其代码的情况。它提供了一种灵活且无侵入性的方式来添加新功能,并允许根据需要组合多个装饰器以实现不同的行为变化

  1. 当你需要在不修改现有对象代码的情况下,动态地给一个对象添加新的行为或功能时,可以使用装饰器模式。它允许你通过包装对象来扩展其功能。
  2. 当你希望能够在运行时选择要添加的特定行为时,装饰器模式非常有用。你可以根据需要动态地组合多个装饰器,以实现不同的行为组合效果。
  3. 当你有一个核心对象,并且希望能够在不影响其他对象的情况下对其进行修改时,装饰器模式是一种很好的选择。由于装饰器模式使用了继承关系,因此你可以针对不同的需求创建多个具体装饰器类,并通过组合它们以满足所需的行为变化。这样就避免了直接修改核心对象的代码。
  4. 当你想要以层次结构的方式动态地组合对象时,可以使用装饰器模式。你可以通过创建多个具体装饰器类并将它们嵌套在一起,形成一个层次结构,从而实现更复杂的行为组合。
  5. 当你想要在不同的时间点为一个对象添加或删除特定行为时,装饰器模式是一个很好的选择。你可以根据需要随时添加或删除特定的装饰器,而不需要修改对象的代码。

装饰器模式中的核心角色包括:

  1. 抽象构件(Component):定义了原始对象和装饰器的公共接口。
  2. 具体构件(Concrete Component):实现了抽象构件的接口,表示原始对象。
  3. 装饰器(Decorator):持有一个抽象构件的引用,并实现了抽象构件接口,用于添加额外的行为或功能。
  4. 具体装饰器(Concrete Decorator):扩展了装饰器的功能,可以在调用原始对象的方法之前或之后执行额外的操作。

装饰器模式代码实践

用装饰模式来完成Coffee的制作具体实现

要求:Coffee有两种款式,浓Coffee和淡Coffee

利用装饰模式加料:牛奶,巧克力

涉及的所有类:

抽象构件:Coffee

java 复制代码
/**
 * coffee制作接口:抽象构件接口,表示咖啡 
 */
ublic interface Coffee {
    String getDescription();//获取对应的描述 
    int getPrice();//获取价格
}

具体构件:LightCoffee、StrongCoffee

java 复制代码
public class LightCoffee implements Coffee{
    @Override    
    public String getDescription() {
        return "you will get a cap of LightCoffee"; 
      }

    @Override    
    public int getPrice() {
        return 18;    
        }
}
/**
 * 浓咖啡
  */
public class StrongCoffee implements Coffee {

    @Override    
    public String getDescription() {
        return "you will get a cap of StrongCoffee";
        }

    @Override    
    public int getPrice() {
        return 20;//浓咖啡价格为十元
       }
}

抽象装饰器:CoffeeDecorator

java 复制代码
/**
 * 实现一个抽象的Coffee装饰器
 */
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    public String getDescription() {
        return coffee.getDescription();
    }

    public int getPrice() {
        return coffee.getPrice();
    }

}

具体装饰器:Chocolate、Milk、Mocha

java 复制代码
public class Chocolate extends CoffeeDecorator {
    public Chocolate(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return coffee.getDescription() + " with Chocolate";
    }

    @Override
    public int getPrice() {
        return coffee.getPrice() + 12;
    }

}

public class Milk extends CoffeeDecorator {

    public  Milk(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return coffee.getDescription()+" with Milk";
    }

    @Override
    public int getPrice() {
        return coffee.getPrice() + 8;
    }

}

public class Mocha extends CoffeeDecorator{
    public Mocha(Coffee coffee) {
        super(coffee);
    }
    @Override
    public String getDescription() {
        return coffee.getDescription()+" with Mocha";
    }

    @Override
    public int getPrice() {
        return coffee.getPrice() +16;
    }

}

运行结果:

java 复制代码
public static void main(String[] args) {
        //创建一杯浓coffee
        Coffee strongCoffee = new StrongCoffee();
        System.out.println(strongCoffee.getDescription() + "~it cost :" + strongCoffee.getPrice());

        //创建一杯带有牛奶的浓coffee
        Coffee strongCoffeeWithMilk = new Milk(strongCoffee);
        System.out.println(strongCoffeeWithMilk.getDescription() + "~it cost :" + strongCoffeeWithMilk.getPrice());

        //创建一杯牛奶和巧克力的淡Coffee
        Coffee lightCoffee = new LightCoffee();
        Coffee lightCoffeeWithMilk = new Milk(lightCoffee);
        Coffee lightCoffeeWithMilkAndChocolate = new Chocolate(lightCoffeeWithMilk);
        System.out.println(lightCoffeeWithMilkAndChocolate.getDescription() + "~it cost :" + lightCoffeeWithMilkAndChocolate.getPrice());

    }

you will get a cap of StrongCoffee~it cost :20

you will get a cap of StrongCoffee with Milk~it cost :28

you will get a cap of LightCoffee with Milk with Chocolate~it cost :38

以上示例演示了如何使用装饰器模式来制作咖啡。通过创建具体的咖啡类和装饰器类,我们可以在运行时动态地添加额外的配料或功能,而不需要修改原始咖啡类的代码。

装饰器模式的优缺点

装饰器模式的优点包括:

  1. 动态扩展功能:装饰器模式允许在运行时动态地为对象添加新的功能,而无需修改现有代码。这使得系统更具灵活性和可扩展性。
  2. 组合多个装饰器:通过使用多个装饰器,你可以在对象上组合不同的功能,以实现各种组合效果。这样可以避免类的继承关系变得过于复杂,提高了代码的可读性和可维护性。
  3. 分离关注点:装饰器模式将功能的添加与核心对象的实现分离开来,使得各个功能模块可以独立开发和测试。这使得代码更加清晰、易于理解和维护。
  4. 遵循开闭原则:装饰器模式符合开闭原则,即对扩展开放,对修改关闭。通过使用装饰器模式,你可以在不修改现有代码的情况下,通过添加新的装饰器来扩展功能。

装饰器模式的缺点包括:

  1. 可能产生过多的小对象:装饰器模式涉及创建多个对象,并将它们嵌套在一起,可能会导致系统中存在大量的小对象。这可能会增加内存使用和运行时开销。
  2. 可能增加复杂度:当装饰器的层次结构变得复杂时,理解和维护代码可能会变得困难。过多的装饰器可能会使代码变得混乱并且难以debug。
  3. 需要注意继承问题:装饰器模式是通过继承来实现的,因此需要特别注意父类与子类之间的关系。如果不正确地设计和使用装饰器模式,可能会导致继承关系变得复杂和脆弱。
相关推荐
不会编程的懒洋洋14 分钟前
Spring Cloud Eureka 服务注册与发现
java·笔记·后端·学习·spring·spring cloud·eureka
赖龙19 分钟前
java程序打包及执行 jar命令及运行jar文件
java·pycharm·jar
U12Euphoria21 分钟前
java的runnable jar采用exe和.bat两种方式解决jre环境的问题
java·pycharm·jar
java小吕布41 分钟前
Java Lambda表达式详解:函数式编程的简洁之道
java·开发语言
程序员劝退师_1 小时前
优惠券秒杀的背后原理
java·数据库
java小吕布1 小时前
Java集合框架之Collection集合遍历
java
一二小选手1 小时前
【Java Web】分页查询
java·开发语言
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ1 小时前
idea 弹窗 delete remote branch origin/develop-deploy
java·elasticsearch·intellij-idea
Code成立1 小时前
《Java核心技术 卷I》用户图形界面鼠标事件
java·开发语言·计算机外设
鸽鸽程序猿2 小时前
【算法】【优选算法】二分查找算法(下)
java·算法·二分查找算法