Java设计模式:装饰器模式
09 Sep 2014注:本文为译文,原文出处java-design-patterns-in-stories
装饰器模式为已存在的对象动态的添加额外的一些功能. 在这篇文章里, 我会用一个简单的例子 - 装饰你的女友 - 来举例说明装饰器模式的原理.
1.装饰器模式小故事
首先, 假设你正在找一个女朋友. 有很多来自不同国家的女孩, 例如:美国, 中国, 日本, 法国等. 她们有着不同的个性与爱好. 在约会网站例如eharmony.com, 如果每个类型的女孩是一个单独的Java类, 那么可能会有成千上万个类. 这是一个严重的问题, 我们称之为”类爆炸”. 此外, 这种设计也是不可扩展的. 只要有一个新的类型出现, 就需要创建一个新的类.
让我们来改变这种设计, 使每个爱好/个性成为一个装饰器, 并且可以动态关联到女孩上.
2.类图
女孩是一个顶层的抽象类, 我们有来在不同国家的女孩. 通过GirlDecorator类, 就可以利用添加新的装饰器来为女孩装饰任何特性.
3.装饰器模式Java代码
Girl.java
public abstract class Girl {
String description = "no particular";
public String getDescription(){
return description;
}
}
AmericanGirl.java
public class AmericanGirl extends Girl {
public AmericanGirl(){
description = "+American";
}
}
EuropeanGirl.java
public class EuropeanGirl extends Girl {
public EuropeanGirl() {
description = "+European";
}
}
GirlDecorator.java
public abstract class GirlDecorator extends Girl {
public abstract String getDescription();
}
Science.java
public class Science extends GirlDecorator {
private Girl girl;
public Science(Girl g) {
girl = g;
}
@Override
public String getDescription() {
return girl.getDescription() + "+Like Science";
}
public void calculateStuff() {
System.out.println("scientific calculation!");
}
}
可以给装饰器无限制的添加更多的方法, 例如: “Dance()”.
Art.java
public class Art extends GirlDecorator {
private Girl girl;
public Art(Girl g) {
girl = g;
}
@Override
public String getDescription() {
return girl.getDescription() + "+Like Art";
}
public void draw() {
System.out.println("draw pictures!");
}
}
Main.java
package designpatterns.decorator;
public class Main {
public static void main(String[] args) {
Girl g1 = new AmericanGirl();
System.out.println(g1.getDescription());
Science g2 = new Science(g1);
System.out.println(g2.getDescription());
Art g3 = new Art(g2);
System.out.println(g3.getDescription());
}
}
输出:
+American
+American+Like Science
+American+Like Science+Like Art
We can also do something like this:
Girl g = new Science(new Art(new AmericanGirl()));
4. 装饰器模式在JSL中的应用
一个典型的装饰器模式的应用就是Java IO.
接下来是一个简单的例子 - BufferedReader 装饰 InputStreamReader.
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//System.in is an InputStream object
InputStreamReader(InputStream in) - 字节流转换为字符流的桥梁. InputSteamReader读取字节并通过指定的字符编码将之转换为字符.
BufferedReader(Reader in) - 在字符流中读取文本并缓冲字符, 从而提供高效的读取方法(例如: readLine()).
comments powered by Disqus