1. 情景
面馆开张了,主营2种面:酸菜面、牛肉面;外加2种配料:鸡蛋、豆皮
用装饰者模式来设计这一订单系统:
满足要求:可以返回点的名称、计算总价格
2. 设计
大体思路:
这里要说的是鸡蛋、豆皮是装饰者,为了让他可以任意的加配料,返回仍是面条类。
类设计图:
3. 实现
面条抽象类
public abstract class Noodle {
String description = "Unknown Name"; public String getDescription() { return description;
} public abstract double cost();
}装饰者抽象类
public abstract class CondimentDecorator extends Noodle {
@Override public abstract String getDescription();
}面条具体类--酸菜面
public class SuancaiNoodle extends Noodle{
SuancaiNoodle() {
description = "Suancai Noodle";
}
@Override public double cost() { return 10;
}
}面条具体类--牛肉面
public abstract class Noodle {
String description = "Unknown Name"; public String getDescription() { return description;
} public abstract double cost();
}配料具体类--鸡蛋
public class Egg extends CondimentDecorator{ private Noodle noodle;
Egg(Noodle noodle) { this.noodle = noodle;
}
@Override public String getDescription() { return noodle.getDescription() + " + Egg";
}
@Override public double cost() { return noodle.cost() + 2;
}
}配料具体类--豆皮
public class SkinOfTofu extends CondimentDecorator{ private Noodle noodle;
SkinOfTofu(Noodle noodle) { this.noodle = noodle;
}
@Override public String getDescription() { return noodle.getDescription() + " + SkinOfTofu";
}
@Override public double cost() { return noodle.cost() + 1;
}
}4. 测试
public class NoodleTest { public static void main(String[] args) {
Noodle suancai = new SuancaiNoodle();
Noodle addEgg = new Egg(suancai);
Noodle addEggSkin = new SkinOfTofu(addEgg);
System.out.println(addEggSkin.getDescription());
System.out.println(addEggSkin.cost());
System.out.println("-----");
Noodle beef = new BeefNoodle();
Noodle addEgg2 = new Egg(beef);
System.out.println(addEgg2.getDescription());
System.out.println(addEgg2.cost());
}
}结果
| 12345 | Suancai Noodle + Egg + SkinOfTofu13.0-----Beef Noodle + Egg14.0 |
5.java I/O
其中InputStream是抽象组件
其下一列如FileInputStream是抽象装饰者,BufferedInputStream是具体装饰者
用法举例
public class ReadFileTest { public static void main(String[] args) { try {
FileInputStream fis = new FileInputStream("jihite/test.json");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedInputStream bis2 = new BufferedInputStream(bis); byte[] b = new byte[bis2.available()];
bis2.read(b);
System.out.println(new String(b));
bis2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}6. 归纳
定义:
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
设计原则:
多组合、少继承
对扩展开放、对修改关闭
优点:
Decorator模式与继承关系的都是要扩展对象,但是Decorator可以提供比继承更多的灵活性
通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合
缺点:
比继承更加灵活也同时意味着更加多的复杂性
导致设计中出现许多小类,如果过度使用,会使程序变得很复杂