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日

相关文章

  • 设计模式系列之组合模式及其在JDK和MyBatis源码中的运用详解

    请看下面的完整攻略: 设计模式系列之组合模式及其在JDK和MyBatis源码中的运用详解 什么是组合模式 组合模式(Composite Pattern),也叫部分-整体模式,是一种结构型设计模式。通过将对象组合成树形结构,以表示“整体-部分”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性,即将对象的组合与单个对象的使用同等对待。 组合模式由…

    Java 2023年5月20日
    00
  • JDK9对String字符串的新一轮优化

    本次讲解将从以下几个方面详细讲解JDK9对String字符串的新一轮优化: 1.记录String字符串的byte数组2.String字符串的实现方式升级到Compact String3.使用try-with-resources自动关闭资源4.String的重复操作5.示例说明 1. 记录String字符串的byte数组 在JDK9中,String字符串可以记…

    Java 2023年5月27日
    00
  • java中日期格式化的大坑

    关于“java中日期格式化的大坑”,我会从以下几个方面进行讲解: Java中日期格式化的基本知识 Java中日期格式化的坑点 解决Java中日期格式化的坑点的方法 两个示例来说明日期格式化的坑点 Java中日期格式化的基本知识 在Java中,要进行日期格式化,需要用到SimpleDateFormat类。该类是线程不安全的类,一般情况下,建议使用ThreadL…

    Java 2023年5月20日
    00
  • SpringSecurity rememberme功能实现过程解析

    下面我给你详细讲解“SpringSecurity rememberme功能实现过程解析”的完整攻略。 1. 简介 Spring Security是一个流行的安全框架,可以为Web应用程序提供身份验证和授权的服务。其中的rememberme功能可以帮助用户在登出后不必重新登录,便能够快速访问应用程序。其实现原理是利用cookie存储用户登录凭据并在下次登录时使…

    Java 2023年5月20日
    00
  • java获取版本号及字节码编译版本方法示例

    Java获取版本号及字节码编译版本方法示例 当我们使用Java开发时,需要知道Java的版本号以及字节码的编译版本。这对于我们在编程过程中的调试与优化非常有帮助。下面就来讲解一下Java获取版本号及字节码编译版本的方法,并且提供两个示例。 获取Java版本号 在Java中,我们可以使用System.getProperty(String key)方法获取Jav…

    Java 2023年5月27日
    00
  • Java连接MongoDB的常用方法详解

    Java连接MongoDB的常用方法详解 MongoDB是一个开源的NoSQL数据库,而Java是一个流行的编程语言。Java连接MongoDB是一个非常常见的需求,本篇文章将会带您详细讲解Java连接MongoDB的常用方法。 1. 准备工作 在连接MongoDB之前,您需要先准备好MongoDB的环境,确保MongoDB正在运行。关于MongoDB的安装…

    Java 2023年5月20日
    00
  • maven下载依赖失败问题及解决

    下面我将为您提供一份“maven下载依赖失败问题及解决”的详细攻略。 问题描述 在使用maven构建项目时,有时候会遇到下载依赖失败的问题。常见的问题包括: 网络连接问题,导致无法从中央仓库下载依赖 依赖库的版本问题,某些依赖库有可能被废弃或者过时 仓库不稳定或者无法访问 解决方法 针对上述问题,我们可以采取以下措施解决: 1. 检查网络连接 网络连接不畅或…

    Java 2023年5月20日
    00
  • java读写二进制文件的解决方法

    JAVA是一种跨平台的编程语言,可以很好地处理二进制文件,本文将介绍在JAVA中读写二进制文件的解决方法。 一、什么是二进制文件 二进制文件是一种特殊类型的计算机文件,其存储格式是二进制的编码,包含了计算机能够读取和使用的信息。二进制文件可以存储各种形式的数据,包括图像、音频、视频、字体等。因为它们是以编程语言可读的方式编写的,二进制文件可以通过计算机程序进…

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