- 浏览: 410923 次
- 性别:
- 来自: 秦皇岛
-
最新评论
-
prayjourney:
了解了,讲的不错
DataInputStream和DataOutputStream类 -
niunianss:
将字节退回的时候,需要添加判断,最后一个字符是英文时,实际数组 ...
PushbackInputStream -
cctt_1:
不要误人子弟,那根本就不是 解释器模式!!!那是Composi ...
Interpreter(解释器)模式 -
java-大神:
[i][i]引用引用引用引用[/img][/img][/img ...
BufferedReader和BufferedWriter -
百合不是茶:
你的程序在文件输入输出流中传入agrs[0]时,会报错越界 ...
DataInputStream和DataOutputStream类
Decorator(装饰器)模式
Decorator模式的意图是在运行时组合操作的新变化.
1.经典范例:流和输出器:
Java类库中输入输出流的设计是应用Decorator模式的典型例子.流是一系列比特或字符的集合,比如文档中出现的字符集合.在Java中,Writer类是支持流的一个方法.有些输出器(writer)类的构造器的参数可以是其他输出器,这样可以基于其他输出器来创建输出器.这种组合就是Decorator模式的最典型结构.在Java中,Decorator模式体现在输出器方面.Decorator模式只需借助很少的代码,就可以大大扩展我们在输入和输出操作中融合小变化的能力.
举个Decorator模式的例子,看看如下代码,它创建一个小的文本文件:
package app.decorator; import java.io.*; public class ShowDecorator{ public static void main(String[] args) throws IOException{ FileWriter file = new FileWriter("sample.txt"); BufferedWriter writer = new BufferedWriter(file); writer.writer("a small amount of sample text"); writer.newLine(); writer.close(); } }
本程序使用FileWriter对象来创建新文件,把这个对象包容在BufferedWriter对象中.本程序需要注意的地方是我们可以从一个流组合另一个流:这部分代码从某FileWriter对象组合得到一个BufferedWriter对象.
在Oozinoz公司,销售人员需要把来自产品数据库的文本格式化为定制消息.这些消息不使用多种多样的字体或者风格,但是现在销售人员希望能够进行格式化调整,使之更加整洁漂亮.为支持这个需求,我们创建了装饰器的框架.这些装饰器类允许我们组合很多种输出过滤器.
为了开发过滤器类的集合,有必要首先创建一个抽象类,这个抽象类定义过滤器希望支持的操作.通过选择已经存在于Writer类中的操作,可以创建继承Writer类所有行为的一个类.图1给出了这种设计思路.
OozinozFilter类是那些装饰输出字符流的类的父类
我们将定义一个过滤器类,其构造器把某输出器作为参数,并且在其write()方法中融合新的行为.
为创建可组合输出流的工具集,下面步骤将介绍一个具有多个关键属性的过滤器超类.该过滤器类将:
(1)支持构造器接收某Writer对象为参数;
(2)充当过滤器类层次的超类;
(3)提供除write(:int)外所有Writer方法的默认实现.
图2给出了这种设计:
OozinozFilter类构造器接收Writer类的任何子类的实例
OozinozFilter类使用如下所示的短小代码来满足其设计目标:
package com.oozinoz.filter; import java.io.*; public abstract class OozinozFilter extends FilterWrite { protected OozinozFilter(Write out){ super(out); } public void write(char cbuf[],int offset,int length) throws IOException{ for(int i=0;i<length;i++) write(cbuf[offset + i]); } public abstract void write(int c) throws IOException; public void write(String s,int offset,int length){ write(s.toCharArray(),offset,length); } }
这部分代码就是保证Decorator模式应用实现所需的代码.OozinozFilter类的子类可以提供write(:int)的新实现,这个实现在把字符传递给底层流的write(:int)之前对其进行修改.OozinozFilter类的其他方法提供子类通常希望得到的行为.该类只是把close()和flush()方法调用留给其父类型(FilterWrite).考虑到抽象的write(:int)方法,OozinozFilter类也解释write(:char[]).
现在,我们很容易创建和使用新的流过滤器.比如,如下代码把文本全部变成小写格式:
package com.oozinoz.filter; import java.io.*; public class LowerCaseFilter extends OozinozFilter { public LowerCaseFilter(Write out){ super(out); } public void write(int c) throws IOException{ out.write(Charater.toLowerCase((char)c)); } }
下面是使用小写过滤器的程序范例:
package app.decorator; import java.io.IOException; import java.io.Writer; import com.oozinoz.filter.ConsoleWriter; import com.oozinoz.filter.LowerCaseWriter; public class ShowLowerCase { public static void main(String[] args) throws IOException{ Writer out = new ConsoleWriter(); out = new LowerCaseFilter(out); out.write("This Text,notably All in LoWeR CasE!"); out.close(); } }
本程序将文本"this text,notably all in lower case!"输出到控制台.
UpperCaseFilter类的代码类似于LowCaseFilter类的代码,差别在于write()方法,代码为:
public void write(int c) throws IOException{ out.write(Character.toUpperCase((char)c)); }
TitleCaseFilter类的代码稍微有些复杂,因为它跟踪空格:
package com.oozinoz.filter; import java.io.*; public class TitleCaseFilter extends OozinozFilter { boolean inWhite = true; public TitleCaseFilter(Writer out){ super(out); } public void write(int c) throws IOException{ out.write(inWhite ? Character.toUpperCase((char)c) :Character.toLowerCase((char)c); inWhite = Character.isWhitespace((char)c) || c == '"'; } }
CommaListFilter类在元素之间加上逗号:
package com.oozinoz.filter; import java.io.IOException; import java.io.Writer; public class CommaListFilter extends OozinozFilter { protected boolean needComma = false; public CommaListFilter(Writer writer){ super(writer); } public void write(int c) throws IOException{ if(needComma){ out.write(','); out.write(' '); } out.write(c); needComma = true; } public void write(String s) throws IOException{ if(needComma) out.write(", "); out.write(s); needComma = true; } }
这些过滤器的主旨是相同的:开发任务主要是选择和重写合适的write()方法.write()方法装饰接收到的文本流,并把修改后的文本继续传递给接下来的流.
突破题:请完成RandomcaseFilter.java的程序代码.
答:一种解决方案如下所示:
package com.oozinoz.filter; import java.io.*; public class RandomCaseFilter extends OozinozFilter { public RandomCaseFilter(Writer out){ super(out); } public void write(int c) throws IOException{ out.write(Math.random()<.5 ? Charater.toLowerCase((char)c): Character.toUpperCase((char)c)); } }
随机大小比较有意思,请参看如下程序代码:
package app.decorator; import java.io.BufferedWrite; import java.io.IOException; import com.oozinoz.filter.ConsoleWriter; import com.oosinoz.filter.RandomCaseFilter; public class ShowRandom { public static void main(String[] args) throws IOException{ BufferedWriter w = new BufferedWriter( new RandomCaseFilter(new ConsoleWriter())); w.writer("buy two packs now and get a zippie pocket rocket -- free!"); w.newLine(); w.close(); } }
此程序使用ConsoleWriter类.运行此程序会得到如下输出.
bUy tWO pAcks NOw ANd geT A ZippIE PoCkEt RocKeT -- frEe!
相对于其他过滤器,WrapFilter类的代码更加复杂.它需要对输出进行居中处理,因此必须缓冲输出,并在传递给后继流之前计算输出字符的数量.代码如下:
package com.oozinoz.filter; import java.io.*; import java.util.*; /** * A WrapFilter object compresses whitespace and wraps text at a specified * width, optionally centering it. The class constructor requires a * BufferedWriter object and the line width. A typical filter class will accept * any Writer object in its constructor. The WrapFilter class requires a * BufferedWriter object because it requires the ability to write newlines in a * platform- independent way, and BufferedWriter supplies this ability. * <p> * The WrapFilter class expects line break indicators to appear as newline * characters. One way to arrange for this is to read input with a * BufferedReader object that handles platform differences in how line breaks * are indicated. * @author Steven J. Metsker */ public class WrapFilter extends OozinozFilter { protected int lineLength; protected StringBuffer lineBuf = new StringBuffer(); protected StringBuffer wordBuf = new StringBuffer(); protected boolean center = false; protected boolean inWhite = false; protected boolean needBlank = false; /** * Construct a filter that will wrap its writes at the specified length. * @param out a writer to which to pass down writes * @param lineLength the length at which to wrap text */ public WrapFilter(BufferedWriter out, int lineLength) { super(out); this.lineLength = lineLength; } /** * Flush and close the stream. * @throws IOException if an I/O error occurs */ public void close() throws IOException { flush(); out.close(); } /** * Write out any characters that were being held, awaiting a full line. * @throws IOException if an I/O error occurs */ public void flush() throws IOException { if (wordBuf.length() > 0) postWord(); if (lineBuf.length() > 0) postLine(); out.flush(); } /** * Write out the characters in the line buffer, optionally centering this * output. */ protected void postLine() throws IOException { if (center) { int adjustment = Math.max(0, (lineLength - lineBuf.length()) / 2); char[] skootch = new char[adjustment]; Arrays.fill(skootch, ' '); out.write(skootch); } out.write(lineBuf.toString()); } /** * Add the word buffer to the line buffer, unless this would make the line * buffer too long. In that case, post the line buffer and then reset the * line buffer to the word buffer. */ protected void postWord() throws IOException { if (lineBuf.length() + 1 + wordBuf.length() > lineLength) { postLine(); ((BufferedWriter) out).newLine(); lineBuf = wordBuf; wordBuf = new StringBuffer(); } else { if (needBlank) lineBuf.append(" "); lineBuf.append(wordBuf); needBlank = true; wordBuf = new StringBuffer(); } } /** * @param center If true, output text will be centered. */ public void setCenter(boolean center) { this.center = center; } /** * Add the given character to the current word buffer, unless the character * is whitespace. Whitespace marks the end of words. On seeing end of a * word, "post" it. * @param c the character to write * @throws IOException if an I/O error occurs */ public void write(int c) throws IOException { if (Character.isWhitespace((char) c)) { if (!inWhite) postWord(); inWhite = true; } else { wordBuf.append((char) c); inWhite = false; } } }
WrapFilter类的构造器接收一个Writer对象和一个width参数,通过后者可以得知从何处换行.你可以混合使用本过滤器和其他过滤器,这样能够产生更多输出结果.比如,如下程序会对输入文本中的文本进行居中、换行以及首字母大写等处理。
package app.decorator; import java.io.*: import com.oozinoz.filter.TitleCaseFilter; import com.oozinoz.filter.WrapFilter; public class ShowFilters { public static void main(String args[]) throws IOException{ BufferedReader in = new BufferedReader(new FileReader(args[0])); Write out = new FileWriter(args[1]); out = new WrapFilter(new BufferedWriter(out),40); //居中显示 out = new TitleCaseFilter(out); //首字母大写 String line; while((line == in.readLine() != null) out.write(line + "\n"); out.close(); in.close(); } }
为查看本程序运行效果,假设输入文本文件包含如下内容:
The "SPACESHOT" shell hovers
at 100 meters for 2 to 3
minutes, erupting star bursts every 10 seconds that
generate ABUNDANT reading-level light for a
typical stadium.
例如如下命令行来执行ShowFilters程序:
>ShowFilters adcopy.txt adout.txt
adout.txt文件的内容应该类似于:
The "Spaceshot" Shell Hovers At 100
Meters For 2 To 3 Minutes, Erupting Star
Bursts Every 10 Seconds That Generate
Abundant Reading-level Light For A
Typical Stadium.
如果不写入文件,也可以把输出字符直接写到控制台。图3给出了Writer类的子类ConsoleWriter的设计思路,把输出字符直接输出到控制台。
ConsoleWriter对象可以作为任何OozinozFilter子类的构造器的参数
突破题:请写出ConsoleWriter.java的代码:
答:
package com.oozinoz.filter; import java.io.Writer; public class ConsoleWriter extends Writer{ public void close(){} public void flush(){} public void write( char[] buffer,int offset,int length) { for(int i=0;i<length;i++) System.out.println(buffer[offset+i]); } }
输入和输出流是Decorator模式在运行时组合对象行为的一个典型例子。Decorator模式的另一个重要的应用是在运行时构建数学函数。
2.函数包装器:
将Decorator模式与把函数作为对象的思想结合起来,就可以在运行时组合出新的函数。这种在运行时创建新函数的能力可以传递给用户,使得他们通过GUI或者简单语言就可以实现新函数。通过把数学函数作为对象而不是新方法来创建,你也可以减少代码中方法的数量,并获得更好的灵活性。
为创建函数装饰器库,我们可以使用类似于I/O流的类结构。对于函数包装器超类名,我们使用Function。对于Function类的最初设计,我们可以模仿OozinozFilter类的设计思路,如图4所示:
函数包装器类层次结构的最初设计,类似于I/O过滤器的设计
OozinozFilter类是FilterWriter类的子类,其构造器可以接收其他Writer对象。Function类的设计与此类似。该类的构造器不接收单个IFunction对象,而是接收一个数组。有些函数,诸如算术函数,需要多个后继函数。
对于函数包装器,没有类像Writer一样已经实现我们所需的操作。因此,对IFunction接口没有实际需求。不使用这个接口可以更简单地定义Funtion类层次结构,如图5所示:
不定义独立的接口,Function类的简化设计也可以实现需求
像OozinozFilter类一样,Function类也定义了其子类必须实现的公共操作。将此操作的名称命名为f。我们可以计划实现参数化函数,所有函数都基于规格化的、变化范围在0--1之间的"time"参数。
对于我们希望包装的每个函数,都将创建Function类的一个子类。图6给出最初的Function类层次结构。
Function的每个子类根据其类名的含义来实现f()
Function超类的代码也许主要用于声明sources数组:
package com.oozinoz.function; /** * This abstract superclass defines the role of a function that wraps itself * around (or "decorates") another function. * * The signature of function methods in this hierarchy is "double f(double time)". * Each class defines this function in a way that is consistent with the class * name. * * The "time" argument is a value from 0 to 1 that represents a normalized * notion of time. For example, in the arc of a parabola, time goes 0 to 1 as x * goes 0 to the base of the arc and y goes 0 to the apogee (at t = .5) and back * to 0. */ public abstract class Function { protected Function[] sources; /** * Construct a function that decorates the provided source function. * * @param f * the source function that this function wraps */ public Function(Function f) { this(new Function[] { f }); } /** * Construct a function that decorates the provided source functions. * * @param sources * the source functions that this function wraps */ public Function(Function[] sources) { this.sources = sources; } /** * The function that subclasses must implement -- see the subclases for * examples. * * @param t * normalized time, a value between 0 and 1 * @return a function value */ public abstract double f(double t); /** * @return a textual representation of this function. */ public String toString() { String name = this.getClass().toString(); StringBuffer buf = new StringBuffer(name); if (sources.length > 0) { buf.append('('); for (int i = 0; i < sources.length; i++) { if (i > 0) buf.append(", "); buf.append(sources[i]); } buf.append(')'); } return buf.toString(); } }
Function子类通常比较简单。比如,下面是Cos类的代码:
package com.oozinoz.function; public class Cos extends Function { public Cos(Function f){ super(f); } public double f(double t){ return Math.cos(sources[0].f(t)); } }
Cos类构造器希望接收一个Function对象参数,并把这个参数继续传递给超类的构造器。Cos.f()方法在时间t时对源函数求值,把该值传递给Math.Cos(),然后返回结果。
Abs类和Sin类几乎与Cos类完全一样。借助于Constant类,我们可以创建拥有一个常量值的Function对象。作为f()方法的调用返回。Arithmetic类接收一个操作符指示器,在其f()方法中会用到。Arithmetic类的代码如下所示:
package com.oozinoz.function; public class Arithmetic extends Function { protected char op; public Arithmetic(char op,Function t1,Function t2){ super(new Function[]{f1,f2}); this.op = op; } public double f(double t){ switch(op){ case '+': return sources[0].f(t)+sources[1].f(t); case '-': return sources[0].f(t)-sources[1].f(t); case '*': return sources[0].f(t)*sources[1].f(t); case '/': return sources[0].f(t)/sources[1].f(t); default: return 0; } } }
T类返回传入的t值。如果希望某变量与时间保持线性变化,这样做很有用处。比如,如下代码创建一个Function对象,随着时间从0变化到1,该对象的f()值从0变化到2 pi:
new Arithmetic('*',new T(),new Constant(2*Math.PI))
可以使用Function类来组合新的数学函数,而无需编写新方法。为了其x和y函数,FunPanel类接收Function对象。这个类也使得这些函数可以在固定面板范围内使用。相关代码如下所示:
package app.decorator; import app.decorator.brightness.FunPanel; import com.oozinoz.function.*; import com.oozinoz.ui.SwingFacade; public class ShowFun { public static void main(String[] args){ Function theta = new Arithemetic('*',new T(),new Constant(2*Math.PI)); Function theta2 = new Arithemetic('*',new T(),new Constant(2*Math.PI*5)); Function x = new Arithemetic('+',new Cos(theta),new Cos(theta2)); Function y = new Arithemetic('+',new Sin(theta),new Sin(theta2)); Funpanel panel = new FunPanel(1000); panel.setPreferredSize(new java.awt.Dimension(200,200)); panel.setXY(x,y); SwingFacade.launch(panel,"Chrysanthemum"); } }
本程序使得一个圆循环出现,运行结果是一组相互嵌套的圆形。
如果希望扩展函数包装器,可以根据需要向Function类层次结构中加入其他的数学函数。
突破题:请编写Exp函数包装器类的代码。
答:代码如下:
package com.oozinoz.function; public class Exp extends Function{ public Exp(Function f)[ super(f); } public double f(double t){ return Math.exp(sources[0].f(t)); } }
假设火药球的亮度是随时间指数下降的正弦函数:
brightness = e^(-4t)*sin(PI*t)
像前面一样,绘制亮度随时间变化的曲线的函数并不需要新的类或者方法:
package app.decorator.brightness; import com.oozinoz.function.*; import com.oozinoz.ui.SwingFacade; public class ShowBrightness { public static void main(String[] args){ FunPanel panel = new FunPanel(); panel.setPreferredSize( new java.awt.Dimension(200,200)); Function brightness = new Arithmetic( '*', new Exp( new Arithmetic('*',new Constant(-4),new T())), new Sin(new Arithmetic('*',new Constant(Math.PI),new T())) ); panel.setXY(new T(),brightnewss); SwingFacade.launch(panel,"Brightness"); } }
这段代码所绘制出的曲线:火药球的高度迅速达到顶点随后便开始衰减。
突破题:请编写代码来定义表示亮度函数的Brightness对象。
答:
package app.decorator.brightness; import com.oozinoz.function.Function; public class Brightnewss extends Function{ public Brightness(Function f){ super(f); } public double f(double f){ return Math.exp(-4*sources[0].f(t))* Math.sin(Math.PI * sources[0].f(t)); } }
我们可以根据需要向Function类层次结构加入其他函数。例如,我们可以加入Random类、Sqrt类以及Tan类。我们也可以创建新的类层次结构来处理其他不同的类型,比如字符串类型。或者,我们还可以采用不同的方法来定义f()操作。例如,我们可以把f()定义为时间的二维或者三维函数。不论创建了什么样的类层次结构,只要使用Decorator模式来包装不同的函数,我们就能够在运行时组合出丰富的函数。
3.与其他模式相关的Decorator模式:
Decorator模式机制中有一个类层次结构到处实现的公共操作。从这个角度来讲,Decorator模式类似于State模式、Strategy模式和Interpreter模式。在Decorator模式中,类通常拥有需要其他后继装饰器对象的构造器。在这一点上,Decorator模式类似于Composite模式。Decorator模式也类似于Proxy模式,因为装饰器类通常通过把调用转发给后继装饰器对象以实现公共操作。
4.小结:
Decorator模式使得我们可以混合某操作的不同变化。经典例子是输入输出流,可以从其他流构造一个新的流。Java类库在其I/O流实现中支持Decorator模式。可以扩展这个思路,创建自己的I/O过滤器集合。在应用程序代码中,我们可以应用Decorator模式来建立函数包装器,这样我们能够根据有限的函数类集合来创建各种各样的函数对象。借助于Decorator模式,我们能够灵活设计具有公共操作的类,可以在运行时集成不同的变化。
发表评论
-
工厂方法模式示例
2009-11-27 14:34 1419//工厂方法模式示例: package innerclass ... -
Flyweight(享元)模式
2009-05-15 21:24 1199Flyweight模式可实现客户 ... -
Builder(生成器)模式
2009-05-15 21:22 1666当构造某对象时,也 ... -
责任链(Chain of Responsibility)模式
2009-05-15 21:18 1861面向对象开发 ... -
Prototype(原型)模式
2009-05-15 21:17 1497Prototype模式不通过实例化类来创建一个新的未初始化的实 ... -
Proxy(代理)模式
2009-05-15 21:14 1549Proxy(代理)模式 ... -
Mediator(中介者)模式
2009-05-15 21:14 1499通常,面向对象的软 ... -
Observer(观察者)模式一
2009-05-15 21:13 1591Observer模式的宗旨是在多个对象之间定义一对多的关系,以 ... -
责任型模式
2009-05-15 21:12 1035对象的责任类似于 ... -
Bridge(桥接模式)
2009-05-15 21:11 1427Bridge模式着重考虑如何实现对具体实现的抽象(ab ... -
Facade外观模式
2009-05-15 21:11 29271.Facade模式就是一个功能介于包和完整应用程序之 ... -
Composite(组合)模式
2009-05-15 21:07 1812Composite模式涉及的是一组对象,其中有些 ... -
Memento(备忘录)模式
2009-05-15 21:07 2221有时候,我们需要创建的对象曾经在系统中出现过。这种情形可能出现 ... -
操作型模式简介
2009-05-15 21:01 1190我们只有弄清楚诸如算法、多态性、方法和操作等术语的不同意 ... -
Template Method(模板方法)模式
2009-05-15 21:01 1103普通方法的方法体 ... -
Template Method二
2009-05-15 20:59 1250Template Method模式类似于Adapter模 ... -
State(状态)模式
2009-05-15 20:58 1469对象的状态是其属性当 ... -
Strategy(策略)模式
2009-05-15 20:55 1096算法是定义好的过程, ... -
Strategy(策略)模式二
2009-05-15 20:54 13862.重构为Strategy模式: ... -
Command(命令)模式
2009-05-15 20:52 1560让方法运行的最常见 ...
相关推荐
“就增加功能来说,Decorator 模式相比生成子类更为灵活” 这句话的含义是,组合比继承更灵活,当可拓展的功能很多时,继承方案会产生大量的子类,而组合可以提
在《Element of Reusable Object-Oriented Software》中,GOF 对装饰器模式的用意进行了概述:Decorator Pattern――Attaches additional responsibilities to an object dynamically. Decorators provide a ...
Python中的装饰器模式是一种设计模式,它允许在不修改原有对象的情况下向其添加新的功能。装饰器模式在Python中有着广泛的应用,特别是在处理诸如认证、权限检查、日志记录、参数检查、同步加锁等与核心业务逻辑无关...
装饰器模式(Decorator)是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式属于结构型模式,是面向对象设计中的一种非常实用的技术。 装饰器模式的核心思想是通过将一个...
4. 具体装饰器(Concrete Decorator):实现了装饰器的抽象方法,并添加新的行为或职责。 在"C#面向对象设计模式纵横谈(10):(结构型模式) Decorator 装饰模式.pdf"中,你可能会学习到如何定义这些角色以及它们之间...
在装饰者模式中,我们通常有两个主要的角色:Component(组件)和Decorator(装饰器)。Component是被装饰的对象接口,定义了所有装饰器和原始对象共同拥有的行为。Concrete Component是Component的具体实现,是实际...
`Decorator`是装饰器,持有`DecoratorComponent`的引用,并实现了相同的操作方法。`AdditionalFeatureA`和`AdditionalFeatureB`是具体装饰器,分别添加了功能A和功能B。 通过以下代码,我们可以创建一个装饰器链并...
23种Python设计模式示例演示源码包,比如包括了工厂模式、Bridge桥接模式、Builder构建模式、Facade外观模式、Adapter适配器模式,Composite组合模式、Decorator装饰器模式,FactoryMethod工厂方法模式、Flyweight享...
装饰器模式(Decorator Pattern)是一种结构型设计模式,主要用于在运行时动态地给对象添加新的职责或行为,而不必改变现有对象的类定义。在面向对象编程中,装饰器模式提供了一种相对于继承更加灵活的方式来增强或...
4. **具体装饰器(Concrete Decorator)**:实现了装饰器接口,为组件增加新的行为或属性。每个具体装饰器都对应一种特定的扩展功能。 装饰模式的优点在于其灵活性,它可以独立于原始对象进行扩展,不需要修改原有...
装饰器模式是一种结构型设计模式,它允许在不修改对象本身的情况下动态地为对象添加新的行为或职责。这种模式在软件工程中广泛应用,特别是在需要扩展已有功能而不影响原有代码结构时。在iOS开发中,装饰器模式同样...
装饰器模式是面向对象设计模式的一种,主要用于在不改变原有对象结构的情况下,动态地为对象增加新的功能。这种模式在Java中尤其常见,因为它允许我们遵循“开闭原则”——对扩展开放,对修改关闭。 装饰器模式的...
c++设计模式-结构型模式-装饰器模式;QT工程;c++简单源码; 装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
装饰器模式是一种设计模式,它的核心思想是动态地给一个对象添加一些额外的职责。这种方式提供了一种扩展原有对象功能的方式,而且并不需要修改原有对象的代码,符合开闭原则(对扩展开放,对修改封闭)。 在装饰器...
4. 具体装饰(Concrete Decorator):装饰器的实现,添加了具体组件的特定增强功能。每个具体装饰类可以添加不同的行为,从而提供多种装饰方式。 举个例子,假设我们有一个`Coffee`类,表示基础的咖啡。`Coffee`...
以上就是"Python装饰器模式学习demo"中涉及的主要内容。通过这个项目,你可以深入理解装饰器的工作原理,以及如何在实际项目中应用它们。实践中,装饰器可用于日志记录、性能测试、权限控制等多种场景,是Python开发...
具体装饰器(Concrete Decorator):扩展装饰器的功能,提供额外的行为 总结 装饰模式通过在运行时动态地为对象添加功能,增强了系统的灵活性和可扩展性。它允许在不修改现有代码的情况下添加新的行为,非常适合于...
在前端开发中,装饰器模式常用于实现AOP(面向切面编程),比如日志记录、性能监控、权限控制等功能。通过定义装饰器函数,可以在不侵入原代码逻辑的情况下,控制代码的执行流程。例如,可以创建一个`logDecorator`...