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());
}
}
结果
Suancai Noodle + Egg + SkinOfTofu
13.0
-----
Beef Noodle + Egg
14.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可以提供比继承更多的灵活性
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合
缺点:
- 比继承更加灵活也同时意味着更加多的复杂性
- 导致设计中出现许多小类,如果过度使用,会使程序变得很复杂