设计模式之装饰器模式

装饰器模式

所有书本都有共性,把他们的共性提到一个父类中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
图片说明

全部评论

相关推荐

03-28 19:11
铜陵学院 C++
有礼貌的山羊追赶太阳:太典了,连笔试都没有开始就因为HC满了而结束了,而且还卡你不让你再投其他部门的。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务