Java設計模式(3)-裝飾者模式

weixin_34239169發表於2018-09-15

一. 學習專案:咖啡館訂單系統

  咖啡館訂單:
  1)咖啡種類:Espresso,ShortBlack,LongBlack,Decaf
  2)調料:Milk,Soy,Chocolate
  3)擴充套件性好,改動方便,維護方便

1.一個差的解決方案:

       飲品超類:
      (1)<abstract>Drink
           description
           getDescription()
           cost()
           
       咖啡單品:
       (1) Decaf
           cost()
           
       (2) ShortBlack
           cost()              
      (3) LongBlack
            cost()
       (4) Espresso
            cost()
        
       新增調料咖啡:
       (1)Espresso && Milk
            cost()
            
       (3)Espresso  && Soy
            cost()
                 
       (3)Espresso && Milk && Soy
            cost()       
            
         ...   
         ...
   擴充性很差,到時可能遇見類爆炸。。。

2. 一個較好的設計方案

飲品超類:
    <abstract>Drink
        desciprtion
        milk
        soy
        chocolate
        
     getDescription()
     cost()
     hasMilk()
     setMilk()
     hasSoy()
     setSoy()
     hasChocolate()
     setChocolate()
 
  咖啡單品:
       (1) Decaf
           cost()
           
       (2) ShortBlack
           cost()              
      (3) LongBlack
            cost()
       (4) Espresso
            cost()
  
 存在一些問題:
   (1)增刪調料種類
   (2)新增多份問題 

3.使用裝飾者模式

 瞭解裝飾者模式
 (1)裝飾者模式就像打包的一個快遞
      1)主體:陶瓷 ,衣服
      2)包裝:報紙填充,塑料泡沫,紙盒,木盒
 (2)Component:
  
  (3)ConcreteComponent 和 Decorator        
  
  (4)裝飾者模式:動態的將新的功能附加到物件上。在物件的擴充套件方面,它比繼承更有彈性。

設計方案:

1.
<abstract>Drink
    description
    getDescription()
    cost()
  
2.
Decorator
   Drink obj
   getDescription()
   cost()
   ...

3.
    
     咖啡單品:
     (1) Decaf
         cost()
         
     (2) ShortBlack
         cost()              
    (3) LongBlack
          cost()
     (4) Espresso
          cost()
          
     調料單品:
     (1)Chocolate
           getDescription()
           cost()
     (2)Milk
           getDescription()
           cost()
     (3)Soy
           getDescription()
           cost()               
    

程式碼實現:

(1) Drink

package com.java.keen.coffeebar;
//飲品類:描述,價格
public abstract class Drink {
    public String description = "";
    private float price = 0f;
    
    public String getDescription() {
        return description+"  "+this.getPrice();
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    
    //花費是一個抽象方法,因為不知道顧客具體選喝啥
    public abstract float cost();
}

(2)Decorator

package com.java.keen.coffeebar.decorator;

import com.java.keen.coffeebar.Drink;

public class Decorator extends Drink{
   private Drink obj;
   public Decorator(Drink obj) {
       this.obj = obj;
   }
    @Override
    public float cost() {
        
        return super.getPrice() +obj.cost();
    }
   public String getDescription() {
       return super.description+"+"+super.getPrice()+"&&"+obj.getDescription();
   }
}

(3)Coffee

package com.java.keen.coffeebar.coffee;

import com.java.keen.coffeebar.Drink;

public class Coffee extends Drink {

    @Override
    public float cost() {
        
        return super.getPrice();
    }
    

}

(4)各種咖啡單品

//1.Decaf
package com.java.keen.coffeebar.coffee;

public class Decaf  extends Coffee{
    public Decaf() {
        super.setDescription("Decaf");
        super.setPrice(3.0f);
    }

}


//2.Espresso
package com.java.keen.coffeebar.coffee;

public class Espresso extends Coffee{
    public Espresso() {
        super.setDescription("Espresso");
        super.setPrice(4.0f);
    }

}

//3.LongBlack
package com.java.keen.coffeebar.coffee;

public class LongBlack  extends Coffee{
    public LongBlack() {
        super.setDescription("LongBlack");
        super.setPrice(5.0f);
    }

}

//4.ShortBlack 
package com.java.keen.coffeebar.coffee;

public class ShortBlack extends Coffee{
    public ShortBlack () {
        super.setDescription("ShortBlack ");
        super.setPrice(6.0f);
    }

}

(5)各種調料單品:

//1.Chocolate
package com.java.keen.coffeebar.decorator;

import com.java.keen.coffeebar.Drink;

public class Chocolate extends Decorator{

    public Chocolate(Drink obj) {
        super(obj);
        // TODO Auto-generated constructor stub
        super.setDescription("Chocolate");
        super.setPrice(3.0f);
    }

}


//2.Milk
package com.java.keen.coffeebar.decorator;

import com.java.keen.coffeebar.Drink;

public class Milk extends Decorator{

    public Milk(Drink obj) {
        super(obj);
        // TODO Auto-generated constructor stub
        super.setDescription("milk");
        super.setPrice(2.5f);
    }

}



//3.Soy
package com.java.keen.coffeebar.decorator;

import com.java.keen.coffeebar.Drink;

public class Soy extends Decorator{

    public Soy(Drink obj) {
        super(obj);
        // TODO Auto-generated constructor stub
        super.setDescription("soy");
        super.setPrice(1.5f);
    }

}

(6)測試類

package com.java.keen.coffeebar;

import com.java.keen.coffeebar.coffee.*;
import com.java.keen.coffeebar.decorator.*;

public class CoffeeBar {
    public static void main(String[] args) {
         Drink order;
         order = new Decaf();
         System.out.println("order1 price:  " +order.cost());
         System.out.println("order1 desc :  "+order.getDescription());
    
         System.out.println("***************");
         order = new LongBlack();
         order = new Milk(order);
         order =new Chocolate(order);
         order =new Chocolate(order);
         System.out.println("order2 price:  " +order.cost());
         System.out.println("order2 desc :  "+order.getDescription());
    
    
    }
}

output:

order1 price:  3.0
order1 desc :  Decaf  3.0
***************
order2 price:  13.5
order2 desc :  Chocolate+3.0&&Chocolate+3.0&&milk+2.5&&LongBlack  5.0

個人在極客學院的學習的筆記

相關文章