Java设计模式之java装饰者模式详解

Java设计模式之装饰者模式详解

什么是装饰者模式?

装饰者模式又叫包装模式,它是一种结构型设计模式。装饰者模式可以在运行时给对象动态添加一些额外的职责,而不影响该对象的行为。其实我们在生活中也经常使用到装饰者模式,比如将一个普通房间粉刷成卧室或客厅,这样就给房间添加了额外的功能,而且不会影响原有房间的结构和功能。

装饰者模式的角色和实现方式

装饰者模式有如下角色:

抽象构件(Component):定义一个抽象接口,用于规范具体构件和装饰对象的行为。

public interface Component {
    void operation();
}

具体构件(ConcreteComponent):实现抽象构件接口的类,也可以称作被装饰器装饰的对象。

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("执行ConcreteComponent的操作");
    }
}

装饰者(Decorator):实现抽象构件(Component)接口的类,并持有一个抽象构件(Component)的引用,用于装饰具体构件的功能。

public abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

具体装饰者(ConcreteDecorator):实现装饰者(Decorator)接口,具体实现装饰者需要扩展Component功能的方法,同时还包含被装饰对象ConcreteComponent。

public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        addBehavior();
    }

    private void addBehavior() {
        System.out.println("装饰添加的行为");
    }
}

装饰者模式的示例

示例1:给文本添加加粗和颜色功能

现在我们需要在文本中添加加粗和颜色的功能,我们可以使用装饰者模式,具体步骤如下:

  1. 首先定义抽象构件:文本Component。
public interface TextComponent {
    void draw();
}
  1. 定义具体构件:普通文本ConcreteText。
public class ConcreteText implements TextComponent {
    private String text;

    public ConcreteText(String text) {
        this.text = text;
    }

    @Override
    public void draw() {
        System.out.print(text);
    }
}
  1. 定义装饰者Decorator:所有装饰器的父类,和Component相同的接口。
public abstract class Decorator implements TextComponent {
    private TextComponent component;

    public Decorator(TextComponent component) {
        this.component = component;
    }

    @Override
    public void draw() {
        component.draw();
    }
}
  1. 定义具体装饰者ConcreteDecorator:实现具体装饰效果。
public class BoldDecorator extends Decorator {
    public BoldDecorator(TextComponent component) {
        super(component);
    }

    @Override
    public void draw() {
        System.out.print("<b>");
        super.draw();
        System.out.print("</b>");
    }
}

public class ColorDecorator extends Decorator {
    private String color;

    public ColorDecorator(TextComponent component, String color) {
        super(component);
        this.color = color;
    }

    @Override
    public void draw() {
        System.out.print("<font color=\"" + color + "\">");
        super.draw();
        System.out.print("</font>");
    }
}
  1. 最后使用装饰者来给文本添加加粗和颜色的功能。
TextComponent text = new ConcreteText("Hello World!");
TextComponent boldText = new BoldDecorator(text);
TextComponent boldRedText = new ColorDecorator(boldText, "red");
boldRedText.draw();

上述代码会输出:

<b><font color="red">Hello World!</font></b>

示例2:给订单添加促销折扣功能

假设我们有一个订单,现在需要为订单添加促销折扣的功能,我们仍然可以使用装饰者模式,具体步骤如下:

  1. 定义抽象构件:订单Component。
public interface OrderComponent {
    double calcCost(); //计算订单费用
}
  1. 定义具体构件:普通订单ConcreteOrder。
public class ConcreteOrder implements OrderComponent {
    private double cost;

    public ConcreteOrder(double cost) {
        this.cost = cost;
    }

    @Override
    public double calcCost() {
        return cost;
    }
}
  1. 定义装饰者Decorator:所有装饰器的父类,和Component相同的接口。
public abstract class Decorator implements OrderComponent{
    private OrderComponent order;

    public Decorator(OrderComponent order) {
        this.order = order;
    }

    @Override
    public double calcCost() {
        return order.calcCost();
    }
}
  1. 定义具体装饰者ConcreteDecorator:实现具体装饰效果。
public class DiscountDecorator extends Decorator {
    private double discount;

    public DiscountDecorator(OrderComponent order, double discount) {
        super(order);
        this.discount = discount;
    }

    @Override
    public double calcCost() {
        return super.calcCost() * discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }
}

public class GiftDecorator extends Decorator {
    private String giftName; 

    public GiftDecorator(OrderComponent order, String giftName) {
        super(order);
        this.giftName = giftName;
    }

    @Override
    public double calcCost() {
        double cost = super.calcCost();
        System.out.println("送一份" + giftName);
        return cost;
    }
}
  1. 最后使用装饰者来给订单添加促销折扣的功能。
OrderComponent order = new ConcreteOrder(100);
OrderComponent discountOrder = new DiscountDecorator(order, 0.8);
OrderComponent giftOrder = new GiftDecorator(discountOrder, "优惠券");
double cost = giftOrder.calcCost();
System.out.println("订单总费用:" + cost);

上述代码会输出:

送一份优惠券
订单总费用:80.0

总结

在需求变化较多或需要动态添加额外功能的情况下,装饰者模式是一种很好的设计模式。但是,由于装饰者模式增加了很多小对象,过度使用也会导致程序变得复杂。在实践中,我们应该根据具体的情况来决定是否使用装饰者模式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java设计模式之java装饰者模式详解 - Python技术站

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

相关文章

  • 详解如何将已有项目改造为Spring Boot项目

    如何将已有项目改造为Spring Boot项目 在本文中,我们将详细讲解如何将已有项目改造为Spring Boot项目的完整攻略,包括以下步骤: 添加Spring Boot依赖 配置Spring Boot启动类 配置Spring Boot配置文件 修改项目结构 配置Spring Boot自动配置 测试Spring Boot项目 1. 添加Spring Boo…

    Java 2023年5月15日
    00
  • 图文详解Maven工程打jar包的N种方式

    图文详解Maven工程打jar包的N种方式 在Maven工程开发中,打jar包是必不可少的步骤之一。本文将介绍多种方式打jar包的方法并逐一详细讲解。下面为大家列出打jar包的多种方法: 通过Maven命令打jar包 通过Maven插件打可执行的jar包 通过Maven插件打普通jar包 通过Maven配置pom.xml文件打jar包 利用Maven打jar…

    Java 2023年5月20日
    00
  • 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)

    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法是目前被广泛使用的一种方式,它能够简化我们对HTTP服务的调用过程,提高我们的开发效率。下面就为大家详细讲解一下这个攻略。 什么是Spring Cloud Feign Spring Cloud Feign是基于Netflix Feign实现的一种服务调用方式。它可以让我们以接…

    Java 2023年5月20日
    00
  • java中的Io(input与output)操作总结(四)

    这里是对“java中的Io(input与output)操作总结(四)”的详细讲解: 一、Io概述 Io(input与output)操作是Java中常用的一种操作方式,它涉及到java.io包中的各种类,我们可以通过Io来读取文件、写入文件、创建文件、删除文件等操作。Java中的Io操作分为输入和输出两个方向,分别由InputStream、Reader和Out…

    Java 2023年5月27日
    00
  • SSH框架网上商城项目第3战之使用EasyUI搭建后台页面框架

    下面是 “SSH框架网上商城项目第3战之使用EasyUI搭建后台页面框架” 的完整攻略。 概述 本文将详细介绍如何使用EasyUI搭建后台管理系统页面框架。具体来说,我们将通过以下步骤实现: 引入EasyUI框架和jQuery库; 编写HTML代码,建立基础的页面框架结构; 编写JavaScript代码,调用EasyUI组件,实现各种页面布局、交互效果和表单…

    Java 2023年5月20日
    00
  • java 学习笔记(入门篇)_java的基础语法

    《Java 学习笔记(入门篇)_Java 的基础语法》是一篇旨在帮助 Java 初学者掌握基础语法的文章。它逐步介绍了 Java 的基础数据类型、运算符、控制语句、数组、面向对象等内容,并给出了一些例子,帮助读者更好地理解这些概念。 以下是该篇攻略的详细介绍: Java 的基础数据类型 Java 的基础数据类型包括整型、浮点型、字符型、布尔型等。这些数据类型…

    Java 2023年5月23日
    00
  • Java中ShardingSphere 数据分片的实现

    非常感谢您对“Java中ShardingSphere 数据分片的实现”的关注。下面是大致的攻略: 1. 什么是ShardingSphere ShardingSphere是一个开源的分布式数据库中间件解决方案,提供数据库分片、分布式事务、数据治理等功能。它由Apache ShardingSphere孵化经过一年多的孵化过程,于2021年2月正式成为Apache…

    Java 2023年5月20日
    00
  • java程序运行时内存分配详解

    Java程序运行时内存分配详解 Java程序运行时内存分配是Java程序员必须理解和掌握的重要知识点之一。了解内存分配可以帮助我们更好的管理内存,提高程序性能,避免程序崩溃等问题的出现。 Java内存分区 在Java中,内存分配主要分为以下几个区域: 程序计数器(Program Counter Register) 虚拟机栈(Java Virtual Mach…

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