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