装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
图来自百度百科
//饮料
public abstract class Beverage {
//描述
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
//计算价格
public abstract double cost();
}
//无咖啡因咖啡
public class Decaf extends Beverage {
public Decaf() {
description = "Decaf";
}
public double cost() {
return 1.64;
}
}
//浓咖啡
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
装饰者
//调料的装饰者类
public abstract class CondimentDecorator extends Beverage {
//重写getDescription()方法
public abstract String getDescription();
}
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ",Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ",Soy";
}
public double cost() {
return .30 + beverage.cost();
}
}
测试类
public class Test {
public static void main(String[] args) {
System.out.println("====================price====================");
System.out.println("Decaf:1.64 Espresso:1.99 Mocha:0.2 Soy:0.3");
System.out.println("====================price====================");
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" +
beverage.cost());
Beverage beverage2 = new Decaf();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Soy(beverage2);
System.out.println(beverage2.getDescription() + " $" +
beverage2.cost());
}
}
输出
====================price====================
Decaf:1.64 Espresso:1.99 Mocha:0.2 Soy:0.3
====================price====================
Espresso $1.99
Decaf,Mocha,Mocha,Soy $2.34
图来自java io流类图
从上图可发现,java.io类设计时利用了装饰者模式,也引出了装饰者模式的一个“缺点”:利用装饰者模式,常常造成设计中有大量的小类,数量过多,可能会造成使用此API程序员的困扰。
编写一个装饰者,把输入流内的所有大写字符转成小写。
装饰者类
//拓展FilterInputStream的装饰者类,实现将大写字符转为小写字符
public class LowerCaseInputStream extends FilterInputStream {
protected LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c: Character.toLowerCase((char)c));
}
public int read(byte b[], int offset, int len) throws IOException {
int result = super.read(b, offset, len);
for(int i = offset; i< offset+result; i++) {
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}
测试类
public class Test {
public static void main(String[] args) throws IOException {
int c;
try {
InputStream in = new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("D:/test.txt")));
while((c = in.read()) >= 0) {
System.out.print((char)c);
}
in.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
读入文件
HELLO WORLD
Hello Zy
输出内容
hello world
hello zy
参考:
《Head First 设计模式》