什么是装饰者模式
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
图来自百度百科
例子
//饮料 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流类图
从上图可发现,java.io类设计时利用了装饰者模式,也引出了装饰者模式的一个“缺点”:利用装饰者模式,常常造成设计中有大量的小类,数量过多,可能会造成使用此API程序员的困扰。
编写自己的Java I/O装饰者
编写一个装饰者,把输入流内的所有大写字符转成小写。
装饰者类
//拓展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 设计模式》