设计模式之装饰器模式
装饰器模式
所有书本都有共性,把他们的共性提到一个父类中Book
public class AppTest{ public static void main(String[] args) { Book book = new C(); System.out.println(book.getDescription()); } } abstract class Book{ private String description; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Book(String description) { this.description = description; } //花费金额 public abstract double cost(); } class C extends Book{ public C() { super("c语言"); } @Override public double cost() { return 98; } }
书本是否升级了电子版和纸质版配套 以及等等功能
应对这种变化
代码可以这也写
是否为C语言类型的电子版纸质版配套创建一个类 class CWithElectronic extends Book{} 是否为C语言类型的配套其他纸质版课本 class CWithOther extends Book{}
这样会使类的数量爆炸
- 针对上面的问题 我们可以添加对应的boolean值来代表是否加了对应的业务
boolean addElectronic; boolean addOther; if(addElectronic)... if(addOther).... 如果以后修改了新的需求 就要加入boolean 新需求 if(是否加了新需求).... 扩展性差
- 类没有爆炸,没有出现各种各样的类
- 新加新的饮料并不会带来什么影响,符合开闭原则
- 但是 添加新调料也就是新需求 就要破坏开闭原则
继装饰器讲解
abstract class Beverage{//饮料 protected String description; public Beverage(String description){ System.out.println(description); this.description = description; } public abstract double getCost(); //调用是这个getDescription 而不是子类中的 public String getDescription() { System.out.println(); return description; } } class Cecaf extends Beverage{//饮料 public Cecaf() { super("无咖啡因的咖啡"); } @Override public double getCost() { return 1; } } //装饰器的核心思想 继承 搭配 组合 // 装饰器的继承并不是“is a”关系 abstract class Condiment extends Beverage{//调料 protected Beverage beverage;//调料关联饮料 public Condiment(Beverage beverage) { super("调料"); this.beverage = beverage;//传入这个 特别关键 } } class Milk extends Condiment{//牛奶调料 public Milk(Beverage beverage) { super(beverage); } @Override public double getCost() { return beverage.getCost() +0.2; } public String getDescription() { return beverage.getDescription()+" 牛奶"; //添加关键 } } class Oil extends Condiment{//油调料 public Oil(Beverage beverage) { super(beverage); } @Override public double getCost() { return beverage.getCost()+0.3; } public String getDescription() { return beverage.getDescription() + " 油"; } } //============================ class Water extends Condiment{ public Water(Beverage beverage) { super(beverage); } @Override public double getCost() { return beverage.getCost()+0.05; } @Override public String getDescription() { return beverage.getDescription()+" 水"; } } public class AppTest{ public static void main(String[] args) { Beverage b = new Cecaf(); //作用是将Milk的参数 b的信息带入Milk 并不会去添加 "料理" 而字符串拼接仅在Milk中 Beverage b1 = new Milk(b); Beverage b2 = new Milk(b1); Beverage b3 = new Water(b2); System.out.println(b3.getCost()); System.out.println(b3.getDescription()); } }
装饰器的UML类图 继承+关联 来实现嵌套迭代效果
装饰器最典型代表 JDK 流 【字节流 字符流z】
自己写一个BufferedReader
- extends Reader : 以后能被包装 传到别的装饰器里
- private Reader in : 用Reader以前的方法 如read 利用读字符的功能来制作其他功能
public class AppTest{ public static void main(String[] args) throws IOException { Reader reader = new FileReader("F:\\a.txt"); MyBufferedReader mbr = new MyBufferedReader(reader); System.out.println(mbr.readLine()); System.out.println(mbr.readLine()); System.out.println(mbr.readLine()); System.out.println(mbr.readLine()); } } class MyBufferedReader extends Reader { private Reader in; public MyBufferedReader(Reader in) { this.in = in; } @Override public int read(char[] chars, int i, int i1) throws IOException { return 0; } @Override public void close() throws IOException { in.close(); } public String readLine() throws IOException { StringBuffer sb = new StringBuffer(); int i; while(true) { i = in.read(); if(i=='\r')//txt换行用\r\n continue; if(i=='\n' || i==-1) break; sb.append((char)i); } if(sb.toString().length()==0){ if(i=='\n') return ""; return null; } else return sb.toString(); } }
可以撤销装饰
https://blog.csdn.net/yqj2065/article/details/73551183