装饰器设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.简介 2.什么是装饰器设计模式 3.实施装饰器设计模式 4.何时使用装饰设计模式 5. Java中的装饰器设计模式 6.下载源代码

1.简介

要了解装饰器设计模式,让我们帮助比萨公司制作一个额外的打顶计算器。 用户可以要求向披萨添加额外的配料,而我们的工作是使用该系统添加配料并提高其价格。

这就像在运行时为我们的披萨对象增加了额外的责任,Decorator Design Pattern适用于此类需求。 但是在此之前,让我们进一步了解这种美丽的图案。

2.什么是装饰器设计模式

装饰器设计模式的目的是动态地将附加职责附加到对象上。 装饰器提供了子类别的灵活替代方案,以扩展功能。

装饰器模式用于动态扩展对象的功能,而无需更改原始类的源或使用继承。 这是通过在实际对象周围创建一个称为Decorator的对象包装来完成的。

Decorator对象设计为具有与基础对象相同的接口。 这允许客户端对象与Decorator对象进行交互,其方式与与基础实际对象进行交互的方式完全相同。 Decorator对象包含对实际对象的引用。 Decorator对象接收来自客户端的所有请求(调用)。 反过来,它将这些调用转发到基础对象。 Decorator对象在将请求转发到基础对象之前或之后添加了一些其他功能。 这确保了可以在运行时从外部将附加功能添加到给定对象,而无需修改其结构。

装饰器可防止子类的泛滥,从而减少复杂性和混乱。 添加功能的任意组合都很容易。 相同的功能甚至可以添加两次。 对于给定的对象,可以同时具有不同的装饰器对象。 客户端可以通过将消息发送到适当的装饰器来选择所需的功能。

decorator_design_pattern_class_diagram_1

图1-类图

零件

  • 为可以动态添加职责的对象定义接口。

混凝土构件

  • 定义可以附加其他职责的对象。

装饰器

  • 维护对Component对象的引用,并定义一个符合Component接口的接口。

混凝土装饰工

  • 向组件添加责任。

3.实施装饰器设计模式

为简单起见,让我们创建一个仅包含两个方法的简单Pizza接口。

package com.javacodegeeks.patterns.decoratorpattern;public interface Pizza {public String getDesc();public double getPrice();
}

getDesc方法用于获取披萨的说明,而getPrice用于获取价格。

以下是两个具体的Pizza类:

package com.javacodegeeks.patterns.decoratorpattern;public class SimplyVegPizza implements Pizza{@Overridepublic String getDesc() {return "SimplyVegPizza (230)";}@Overridepublic double getPrice() {return 230;}}
package com.javacodegeeks.patterns.decoratorpattern;public class SimplyNonVegPizza implements Pizza{@Overridepublic String getDesc() {return "SimplyNonVegPizza (350)";}@Overridepublic double getPrice() {return 350;}}

装饰器包装需要增加功能的对象,因此需要实现相同的接口。 下面是一个抽象装饰器类,它将由所有具体装饰器扩展。

package com.javacodegeeks.patterns.decoratorpattern;public abstract class PizzaDecorator implements Pizza {@Overridepublic String getDesc() {return "Toppings";}}

以下是具体的装饰器类。

package com.javacodegeeks.patterns.decoratorpattern;public class Broccoli extends PizzaDecorator{private final Pizza pizza;public Broccoli(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Broccoli (9.25)";}@Overridepublic double getPrice() {return pizza.getPrice()+9.25;}}
package com.javacodegeeks.patterns.decoratorpattern;public class Cheese extends PizzaDecorator{private final Pizza pizza;public Cheese(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Cheese (20.72)";}@Overridepublic double getPrice() {return pizza.getPrice()+20.72;}}
package com.javacodegeeks.patterns.decoratorpattern;public class Chicken extends PizzaDecorator{private final Pizza pizza;public Chicken(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Chicken (12.75)";}@Overridepublic double getPrice() {return pizza.getPrice()+12.75;}}
package com.javacodegeeks.patterns.decoratorpattern;public class FetaCheese extends PizzaDecorator{private final Pizza pizza;public FetaCheese(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Feta Cheese (25.88)";}@Overridepublic double getPrice() {return pizza.getPrice()+25.88;}}
package com.javacodegeeks.patterns.decoratorpattern;public class GreenOlives extends PizzaDecorator{private final Pizza pizza;public GreenOlives(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Green Olives (5.47)";}@Overridepublic double getPrice() {return pizza.getPrice()+5.47;}}
package com.javacodegeeks.patterns.decoratorpattern;public class Ham extends PizzaDecorator{private final Pizza pizza;public Ham(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Ham (18.12)";}@Overridepublic double getPrice() {return pizza.getPrice()+18.12;}}
package com.javacodegeeks.patterns.decoratorpattern;public class Meat extends PizzaDecorator{private final Pizza pizza;public Meat(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Meat (14.25)";}@Overridepublic double getPrice() {return pizza.getPrice()+14.25;}}
package com.javacodegeeks.patterns.decoratorpattern;public class RedOnions extends PizzaDecorator{private final Pizza pizza;public RedOnions(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Red Onions (3.75)";}@Overridepublic double getPrice() {return pizza.getPrice()+3.75;}}
package com.javacodegeeks.patterns.decoratorpattern;public class RomaTomatoes extends PizzaDecorator{private final Pizza pizza;public RomaTomatoes(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Roma Tomatoes (5.20)";}@Overridepublic double getPrice() {return pizza.getPrice()+5.20;}}
package com.javacodegeeks.patterns.decoratorpattern;public class Spinach extends PizzaDecorator{private final Pizza pizza;public Spinach(Pizza pizza){this.pizza = pizza;}@Overridepublic String getDesc() {return pizza.getDesc()+", Spinach (7.92)";}@Overridepublic double getPrice() {return pizza.getPrice()+7.92;}}

我们需要用这些浇头装饰披萨对象。 上面的类包含对需要装饰的披萨对象的引用。 装饰器对象在调用装饰器的函数后将其功能添加到装饰器。

package com.javacodegeeks.patterns.decoratorpattern;import java.text.DecimalFormat;public class TestDecoratorPattern {public static void main(String[] args) {DecimalFormat dformat = new DecimalFormat("#.##");Pizza pizza = new SimplyVegPizza();pizza = new RomaTomatoes(pizza);pizza = new GreenOlives(pizza);pizza = new Spinach(pizza);System.out.println("Desc: "+pizza.getDesc());System.out.println("Price: "+dformat.format(pizza.getPrice()));pizza = new SimplyNonVegPizza();pizza = new Meat(pizza);pizza = new Cheese(pizza);pizza = new Cheese(pizza);pizza = new Ham(pizza);System.out.println("Desc: "+pizza.getDesc());System.out.println("Price: "+dformat.format(pizza.getPrice()));}}

上面的代码将产生以下输出:

Desc: SimplyVegPizza (230), Roma Tomatoes (5.20), Green Olives (5.47), Spinach (7.92)
Price: 248.59
Desc: SimplyNonVegPizza (350), Meat (14.25), Cheese (20.72), Cheese (20.72), Ham (18.12)
Price: 423.81

在上面的类中,我们首先创建了SimplyVegPizza ,然后用RomaTomatoesGreenOlivesSpinach装饰它。 输出中的desc显示添加在SimplyVegPizza中的浇头,且价格为所有价格的总和。

我们对SimplyNonVegPizza做了同样的事情,并在SimplyNonVegPizza添加了不同的SimplyNonVegPizza 。 请注意,您可以为一个对象多次装饰同一件事。 在上面的示例中,我们两次添加了cheese ; 它的价格也增加了两倍,可以在输出中看到。

当您需要在运行时为对象添加额外功能并对其进行修改时,Decorator设计模式看起来不错。 但这会导致很多小物体。 使用Decorator的设计通常会导致系统由许多看起来相似的小对象组成。 对象的区别仅在于它们的互连方式不同,不在于它们的类或变量的值。 尽管这些系统很容易被了解它们的人定制,但是它们可能很难学习和调试。

4.何时使用装饰设计模式

在以下情况下,请使用Decorator模式:

    • 动态透明地向单个对象添加职责,即不影响其他对象。
    • 对于可以撤消的责任。
    • 当通过子类扩展不可行时。 有时可能会有大量独立的扩展,并且会产生大量的子类来支持每种组合。 或者,类定义可能被隐藏或无法用于子类化。

5. Java中的装饰器设计模式

      • java.io.BufferedInputStream(InputStream)
      • java.io.DataInputStream(InputStream)
      • java.io.BufferedOutputStream(OutputStream)
      • java.util.zip.ZipOutputStream(OutputStream)
      • java.util.Collections#checked[List|Map|Set|SortedSet|SortedMap]()

6.下载源代码

这是关于装饰设计模式的课程。

您可以在此处下载相关的源代码: DecoratorPattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/decorator-design-pattern.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5.1.2全景声音箱摆位_如何体验全景声

如何体验全景声(科普)要想体验全景声,三大要素不可少。1、输出设备:支持全景声的播放设备,比如碟机,比如电视盒子,比如XBOXONEX。如果电视和音响都支持EARC,则可以不用播放设备&…

JavaScript测验——未初始化的变量---第5关

校验规则 当你用一个值是undefined的变量来做字符串拼接操作的时候,它会输出字符串"undefined"。 闯关: 定义 3 个变量a、b、c,并且分别给他们赋值:3、9、"I am pretty",这样它们值就不会是undefined了。

Java中使用Socket实现服务器端和客户端通讯

创建服务器端serverSocket 1 import java.io.BufferedReader;2 import java.io.IOException;3 import java.io.InputStream;4 import java.io.InputStreamReader;5 import java.io.OutputStream;6 import java.io.PrintWriter;7 import java.net.ServerSocket;8 import java.ne…

修改telnet提示并非_俊翔:修改ECU数据解除奔驰GL350尿素限制

为达到排放要求,很多乘用柴油车都要加尿素(Adblue),以降低废气排放。在轿车维修当中,最常见的有奔驰GL350、路虎揽胜出现尿素锁定。仪表上提示加尿素,并且限制启动次数。每当把发动机熄火再启动一次,次数就会减少&…

JavaScript测验——变量名大小写---第6关

校验规则 例如: var userName; var userLoginFlag;闯关: 修改已声明的变量,让它们的命名符合驼峰命名法的规范。 这个需要注意的是在声明和赋值时都应该使用驼峰命名法。

python编码规范

python编码规范 文件及目录规范 文件保存为 utf-8 格式。程序首行必须为编码声明:# -*- coding:utf-8 -*-文件名全部小写。代码风格 空格 设置用空格符替换TAB符。代码缩进为4个空格符。仅在运算符前后(如,-,,)各加一个空格,不要在…

redux异步action_React躬行记(12)——Redux中间件

Redux的中间件(Middleware)遵循了即插即用的设计思想,出现在Action到达Reducer之前(如图10所示)的位置。中间件是一个固定模式的独立函数,当把多个中间件像管道那样串联在一起时,前一个中间件不…

java方法示例注释 @_Java注释和真实世界的Spring示例

java方法示例注释 “注释”是编程语言定义的一种,并用作“标记”。 可以将它们视为编程语言引擎可以理解的注释行。 它们不会直接影响程序的执行,但会直接影响程序的执行。 定义 注释使用interface关键字定义,并且与接口相似。 它具有定义类…

监控与管理

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中,向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来,您将深入研究Spring Integration的基础知识,例如通道,转换器和适…

郑州智慧岛大数据管委会_数据科学融通应用数学 ‖ 智慧岛大讲堂

8月6日上午,郑东新区智慧岛大数据实验区管委会,举办了“数据科学融通应用数学”专题智慧岛大讲堂讲座,邀请到北京大学数学科学学院副教授、大数据分析与应用技术国家工程实验室郑州数字创新中心主任卢朓为本次大讲堂活动做主题分享&#xff0…

浏览器中的WebSocket(ws://127.0.0.1:9988);

<script type"text/javascript">function WebSocketTest(){if ("WebSocket" in window){alert("您的浏览器支持 WebSocket!");// 打开一个 web socketvar ws new WebSocket("ws://localhost:9998/echo");ws.onopen function()…

db2 获取返回的游标_MySQL ------ 存储过程与游标简单使用

存储过程小例子如完成以下事情&#xff0c;获得与之前一样的订单合计&#xff0c;但需要对合计增加营业税&#xff0c;不过只针对某些顾客主要就是&#xff1a;1、获得合计2、把营业税有条件的添加到合计 3、返回合计&#xff08;带或不带税&#xff09;delimiter $$-- 存储过程…

hdu_5761_Rower Bo(xjb猜公式)

题目链接&#xff1a;hdu_5761_Rower Bo 题意&#xff1a; 让你求一个物理问题 题解&#xff1a; xjb猜公式&#xff0c;由题目样例可得&#xff0c;答案为8/7&#xff0c;然后我们可以xjb猜出公式为v1*a/(v1*v1-v2*v2)&#xff0c;然后特判一下a0和v1<v2的情况就OK 1 #incl…

netbeans 源文件_具有NetBeans,嵌入式GlassFish,JPA和MySQL数据源的Arquillian

netbeans 源文件这是一个偶然的帖子。 我一直在研究交易CDI观察者&#xff0c;并尝试使用嵌入式GlassFish对它进行一些集成测试。 但是令人惊讶的是&#xff0c;这种方法不能很好地工作&#xff0c;我仍在弄清楚&#xff0c;使用普通的嵌入式GlassFish时问题出在哪里。 同时&am…

vue 子父组件周期顺序_父组件和子组件生命周期钩子执行顺序是什么?

加载页面执行步骤1、父组件&#xff1a;beforeCreate -> created -> beforeMount2、子组件&#xff1a;beforeCreate -> created -> beforeMount -> mounted3、父组件&#xff1a;mounted销毁组件执行步骤1、父组件&#xff1a;beforeDestroy2、子组件&#xff…