java实现装饰器模式(Decorator Pattern)

Java实现装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许我们动态地将行为添加到某个对象中,而不是通过继承来实现。它是在保持类方法签名不变的情况下增加功能,实现类的功能扩展。

角色介绍

  • Component:抽象组件,定义装饰者和被装饰者的最基本的接口和规范。
  • ConcreteComponent:具体组件,也是被装饰器装饰的基本对象,实现抽象组件中的方法。
  • Decorator:抽象装饰器,实现了Component接口,并且持有一个被装饰者的引用。旨在为后续的具体装饰器提供代理或者委托相应的行为扩展。
  • ConcreteDecorator:具体装饰器,继承Decorator,重写接口中的方法,完成相应的装饰逻辑。

示例1:文字消息发送功能

我们需要设计一个具有文字消息发送能力的聊天应用,但是仅仅有文字消息发送的聊天,显然这个应用并不太好用。所以,我们需要实现添加表情和图片消息的功能。

我们可以将文字消息发送功能抽象为一个Component类,即AbstractMessageSender类,然后定义三个装饰器:EmoticonMessageSender、PictureMessageSender和RedPacketMessageSender,分别用于装饰Component类,实现添加表情、图片和红包消息的功能。

public abstract class AbstractMessageSender {
    public abstract void sendMessage();
}

public class TextMessageSender extends AbstractMessageSender {
    @Override
    public void sendMessage() {
        System.out.println("发送了一条文字消息");
    }
}

public abstract class MessageSenderDecorator extends AbstractMessageSender {
    protected AbstractMessageSender messageSender;

    public MessageSenderDecorator(AbstractMessageSender messageSender) {
        this.messageSender = messageSender;
    }

    public void sendMessage() {
        messageSender.sendMessage();
    }
}

public class EmoticonMessageSender extends MessageSenderDecorator {
    public EmoticonMessageSender(AbstractMessageSender messageSender) {
        super(messageSender);
    }

    @Override
    public void sendMessage() {
        super.sendMessage();
        System.out.println("带有表情的消息");
    }
}

public class PictureMessageSender extends MessageSenderDecorator {
    public PictureMessageSender(AbstractMessageSender messageSender) {
        super(messageSender);
    }

    @Override
    public void sendMessage() {
        super.sendMessage();
        System.out.println("带有图片的消息");
    }
}

public class RedPacketMessageSender extends MessageSenderDecorator {
    public RedPacketMessageSender(AbstractMessageSender messageSender) {
        super(messageSender);
    }

    @Override
    public void sendMessage() {
        super.sendMessage();
        System.out.println("带有红包的消息");
    }
}

使用示例代码:

AbstractMessageSender textMessageSender = new TextMessageSender();
textMessageSender = new EmoticonMessageSender(textMessageSender);
textMessageSender = new PictureMessageSender(textMessageSender);
textMessageSender = new RedPacketMessageSender(textMessageSender);
textMessageSender.sendMessage();

运行结果为:

发送了一条文字消息
带有表情的消息
带有图片的消息
带有红包的消息

示例2:饮料点单系统

我们现在要实现一个简单的点单系统,基础饮料有红茶、绿茶和奶茶,但是用户可以选择加入椰果、芋头、珍珠等等不同口味的配料。这些配料是新增的,我们不希望因为新的加入而修改原本的代码,更好的方法是采用装饰器模式。

我们定义一个抽象类Beverage,表示基础饮料。具体的基础饮料类RedTea、GreenTea和MilkTea实现Beverage接口,然后配料类可以继承或实现Beverage接口,形成装饰器类Milk、Pearl、Coconut等。

public abstract class Beverage {
    protected String name;

    public String getName() {
        return name;
    }

    public abstract double cost();
}

public class RedTea extends Beverage {
    public RedTea() {
        super.name = "红茶";
    }

    public double cost() {
        return 10;
    }
}

public class GreenTea extends Beverage {
    public GreenTea() {
        super.name = "绿茶";
    }

    public double cost() {
        return 8;
    }
}

public class MilkTea extends Beverage {
    public MilkTea() {
        super.name = "奶茶";
    }

    public double cost() {
        return 12;
    }
}

public abstract class CondimentDecorator extends Beverage {
    protected Beverage beverage;

    public abstract String getName();

    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}

public class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    public String getName() {
        return beverage.getName() + " 加牛奶";
    }

    public double cost() {
        return 2.5 + beverage.cost();
    }
}

public class Pearl extends CondimentDecorator {
    public Pearl(Beverage beverage) {
        super(beverage);
    }

    public String getName() {
        return beverage.getName() + " 加珍珠";
    }

    public double cost() {
        return 3.5 + beverage.cost();
    }
}

public class Coconut extends CondimentDecorator {
    public Coconut(Beverage beverage) {
        super(beverage);
    }

    public String getName() {
        return beverage.getName() + " 加椰果";
    }

    public double cost() {
        return 3 + beverage.cost();
    }
}

使用示例代码:

Beverage redTea = new RedTea();
System.out.println(redTea.getName() + ",价格:" + redTea.cost());

Beverage milkWithGreenTea = new Milk(new GreenTea());
System.out.println(milkWithGreenTea.getName() + ",价格:" + milkWithGreenTea.cost());

Beverage pearlWithMilkTea = new Pearl(new MilkTea());
System.out.println(pearlWithMilkTea.getName() + ",价格:" + pearlWithMilkTea.cost());

Beverage coconutWithGreenWithMilkTea = new Coconut(new Milk(new GreenTea()));
System.out.println(coconutWithGreenWithMilkTea.getName() + ",价格:" + coconutWithGreenWithMilkTea.cost());

运行结果为:

红茶,价格:10.0
绿茶 加牛奶,价格:10.5
奶茶 加珍珠 加牛奶,价格:18.5
绿茶 加牛奶 加椰果,价格:13.5

总结

装饰器模式通过组合的方式,动态地实现增加属性和功能,同时也保证了被装饰器装饰的原对象不会被修改,这种方式增强扩展性更好。但是如果装饰器的嵌套层数过深,可能会影响代码阅读的效率。在设计模式的选择上,应根据具体的需求和情况来进行考虑。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java实现装饰器模式(Decorator Pattern) - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解Spring Kafka中关于Kafka的配置参数

    下面我来详细讲解一下关于“详解Spring Kafka中关于Kafka的配置参数”的完整攻略。 1. Kafka中常用的配置参数 在使用Kafka时,可以通过配置不同的参数来更加灵活地自定义Kafka的行为。下面是Kafka中一些常用的配置参数: bootstrap.servers:Kafka集群的连接地址列表,指定了Kafka Broker的主机名和端口号…

    Java 2023年5月20日
    00
  • 开发实例:JSP中实现全文检索

    下面我将详细讲解“开发实例:JSP中实现全文检索”的完整攻略,包括开发环境的搭建、代码实现、运行调试等内容。 开发环境搭建 在进行本项目的开发之前,我们需要准备好以下工具: Java 8及以上版本 Apache Tomcat 8及以上版本 Eclipse IDE 步骤: 安装Java并设置环境变量; 下载并解压Tomcat,配置Tomcat的环境变量; 下载…

    Java 2023年6月15日
    00
  • Java创建对象之显示创建与隐式创建

    Java创建对象之显示创建与隐式创建 在Java语言中,创建对象有两种方式:显示创建和隐式创建。本文将对这两种方式进行详细讲解。 显示创建 1. 使用new关键字 使用new关键字创建对象是最常见的方式。new关键字会在堆内存中为对象分配空间,并返回对象的引用。示例如下: // 创建 String 对象 String str1 = new String(&q…

    Java 2023年5月26日
    00
  • 基于MyBatis的数据持久化框架的使用详解

    基于 MyBatis 的数据持久化框架的使用详解 什么是 MyBatis MyBatis 是一种开源的持久化框架,简单地将 SQL 语句与 Java 对象进行映射。它可以轻松地将复杂的 SQL 语句映射到可维护的 Java 对象中。 MyBatis 提供了一些内置工具和插件,可以大大简化开发人员编写持久层代码的工作。 MyBatis 的使用 在使用 MyBa…

    Java 2023年5月20日
    00
  • Eclipse+Java+Swing+Mysql实现工资管理系统

    Eclipse+Java+Swing+Mysql实现工资管理系统攻略 1. 系统概述 工资管理系统是企业内部薪资管理的重要组成部分,其任务是集中管理员工的薪资及相关信息。本系统采用Eclipse+Java+Swing+Mysql技术实现,具备以下功能模块: 登录模块:提供登录界面,验证用户身份。 员工信息管理:添加、删除员工及修改员工信息。 薪资管理:计算、…

    Java 2023年5月30日
    00
  • Spring学习笔记之bean生命周期

    Spring学习笔记之Bean生命周期 什么是Bean生命周期 在Spring容器中,当我们需要获取一个Bean实例时,会经历一系列的过程,包括BeanDefinition解析、Bean实例化、属性注入和初始化等操作,最终才能得到我们所需要的Bean实例。这整个过程就称之为Bean生命周期。 Bean生命周期可以分为以下几个阶段: 实例化:根据BeanDef…

    Java 2023年5月31日
    00
  • 深入理解JavaScript中的对象

    深入理解JavaScript中的对象 什么是JavaScript中的对象 在JavaScript中,对象是一种复合数据类型,可以将它们看作是键值对的集合,其中每个键都是字符串类型,每个值可以是任何数据类型,包括更多的对象。JavaScript中的对象有两种基本类型:内置对象和自定义对象。内置对象指的是在JavaScript中已经定义好的对象,例如Math、D…

    Java 2023年5月26日
    00
  • Java通过工厂、Map容器创建对象的方法

    Java通过工厂、Map容器创建对象的方法可以极大地提高代码的可读性和复用性,下面是详细的攻略。 1. 工厂模式创建对象 工厂模式是一种创建对象的设计模式,它定义一个接口,让子类决定实例化哪一个类。工厂模式使一个类的实例化延迟到其子类中进行。 使用工厂模式的好处是,我们可以使用相同的方法来创建不同的对象,而不需要暴露实例化逻辑给客户端。这种方式可以将客户端代…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部