設計模式學習筆記之裝飾者模式
裝飾者模式簡單點說就是:在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。
設計關係圖如下:
這樣說,肯定比較抽象,下面我們來舉個例子:
假如我想開個麵館(在顯示生活中我真的想開個麵館啊!)。
為了能更好的賺錢,我肯定要推出各種各樣的面類菜品。但其實基本全部的面都是由四種基本的面組成的:細面,寬面,刀削麵和貓耳面。在這四種面的基礎上,我們可以加入,青菜,雞蛋,牛肉,組合出青菜細面,雞蛋寬面,牛肉刀削麵,青菜雞蛋貓耳面等等。。現在為了方便我們的前臺收銀的服務員,我們來實現一個訂單收銀系統。
首先我們想到的設計思路肯定是先設計一個食物的父類然後為每一種不同品種的麵條設計一種子類。比如,青菜刀削麵類、牛肉刀削麵類,雞蛋細面類。。。。
這樣設計的壞處就是擴充套件子類太多,不好維護,如果後期有新加入幾種配菜品類,比如羊肉,番茄等等,這就會多出很多類,也不便於擴充套件。而且可能會出現類似於機器學習中的‘維度災難’的類災難的問題
如果我們對上面的想法來改進一下呢,我們把四種基本面都做成各自的類,然後把配菜做成各自的類,最後在計算總價的時候將他們相加。
這種設計雖然對比與第一種設計思想,不會出現類災難的問題,但是當出現新的品類是還是需要修改主類中的部分功能比如:加和,所以還是不易維護的。
所以接下來就引入了我們的裝飾者模式的設計方案了。
先給出裝飾者的設計思路
基類,食物類
public abstract class Food {
//描述屬性
public String description="";
//價格屬性
private float price=0f;;
//設定描述
public void setDescription(String description)
{
this.description=description;
}
//獲取描述
public String getDescription()
{
return description+"-"+this.getPrice();
}
//獲取價格
public float getPrice()
{
return price;
}
//設定價格
public void setPrice(float price)
{
this.price=price;
}
//價格計算
public abstract float cost();
}
public class Noodle extends Food {
//計算價格
@Override
public float cost() {
// TODO Auto-generated method stub
return super.getPrice();
}
}
細面類
public class ThinNoodle extends Noodle {
public ThinNoodle()
{
super.setDescription("細面");
super.setPrice(6.0f);
}
}
public class WideNoodle extends Noodle{
public WideNoodle()
{
super.setDescription("寬面");
super.setPrice(6.0f);
}
}
public class CutNoodle extends Noodle{
public CutNoodle()
{
super.setDescription("刀削麵");
super.setPrice(7.0f);
}
}
貓耳面(原諒我可憐的英語吧。。)
public class CatEarNoodle extends Noodle{
public CatEarNoodle()
{
super.setDescription("貓耳面");
super.setPrice(8.0f);
}
}
裝飾者類
public class Decorator extends Food {
//食物類負責接受傳進來的基本面條類並進行裝飾
private Food Obj;
//建構函式
public Decorator(Food Obj){
this.Obj=Obj;
};
//價格計算
@Override
public float cost() {
// TODO Auto-generated method stub
return super.getPrice()+Obj.cost();
}
//得到描述資訊
@Override
public String getDescription()
{
return super.description+"-"+super.getPrice()+"&&"+Obj.getDescription();
}
}
青菜類
public class Vegetables extends Decorator {
public Vegetables(Food Obj) {
super(Obj);
// TODO Auto-generated constructor stub
super.setDescription("青菜");
super.setPrice(1.5f);
}
}
public class Egg extends Decorator {
public Egg(Food Obj) {
super(Obj);
// TODO Auto-generated constructor stub
super.setDescription("雞蛋");
super.setPrice(2.0f);
}
}
public class Beef extends Decorator {
public Beef(Food Obj) {
super(Obj);
// TODO Auto-generated constructor stub
super.setDescription("牛肉");
super.setPrice(5.0f);
}
}
讓我們寫一個測試程式測試一下:
public class NoodleShop {
public static void main(String[] args) {
Food order;
order=new ThinNoodle();
System.out.println("一號訂單價格:"+order.cost());
System.out.println("一號訂單描述:"+order.getDescription());
System.out.println("#######################################");
order=new CutNoodle();
order=new Beef(order);
order=new Egg(order);
order=new Egg(order);
System.out.println("二號訂單價格:"+order.cost());
System.out.println("二號訂單描述:"+order.getDescription());
System.out.println("#######################################");
order=new CatEarNoodle();
order=new Beef(order);
order=new Egg(order);
order=new Vegetables(order);
System.out.println("三號訂單價格:"+order.cost());
System.out.println("三號訂單描述:"+order.getDescription());
}
}
看來我們非常成功的完成了我們的麵店訂單收銀系統
那麼我們來看看裝飾者模式的優缺點和適用場景:
優點:
1.裝飾者模式可以提供比繼承更多的靈活性。
2.可以通過一種動態的方式來擴充套件一個物件的功能,在執行時選擇不同的裝飾器,從而實現不同的行為。
3.通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一物件,得到功能更為強大的物件。
4.具體構件類與具體裝飾類可以獨立變化,使用者可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有程式碼無須改變,符合“開-閉原則”。
缺點:
1.會產生很多的小物件,增加了系統的複雜性
2.這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯,排錯也很困難,對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為煩瑣。
適用場景:
1. 需要擴充套件一個類的功能,或給一個類新增附加職責。
2. 需要動態的給一個物件新增功能,這些功能可以再動態的撤銷。
3. 需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
相關文章
- 設計模式讀書筆記之介面卡模式、裝飾者模式設計模式筆記
- 設計模式學習筆記(3)裝飾器設計模式筆記
- 設計模式之裝飾者模式設計模式
- PHP設計模式之裝飾者模式PHP設計模式
- 設計模式之裝飾者模式(二)設計模式
- 設計模式之裝飾者模式(一)設計模式
- Java設計模式之裝飾者模式Java設計模式
- 設計模式學習筆記(十)裝飾器模式及其應用設計模式筆記
- Head First 設計模式筆記 3.裝飾者模式設計模式筆記
- 設計模式——裝飾者模式設計模式
- 設計模式-裝飾者模式設計模式
- [設計模式]裝飾者模式設計模式
- 設計模式學習-裝飾模式,橋接模式設計模式橋接
- Java學設計模式之裝飾器模式Java設計模式
- 8.java設計模式之裝飾者模式Java設計模式
- 設計模式(十一)----結構型模式之裝飾者模式設計模式
- 小白設計模式:裝飾者模式設計模式
- 設計模式學習筆記之工廠模式設計模式筆記
- 設計模式系列之「裝飾模式」設計模式
- 設計模式之-裝飾器模式設計模式
- 設計模式之【裝飾器模式】設計模式
- 《laravel 框架關鍵技術解析》學習筆記之裝飾者模式Laravel框架筆記模式
- 每天一個設計模式之裝飾者模式設計模式
- 軟體設計模式學習(十三)裝飾模式設計模式
- 設計模式系列10–裝飾者模式設計模式
- Java設計模式(3)-裝飾者模式Java設計模式
- Go 設計模式之裝飾器模式Go設計模式
- java設計模式之裝飾器模式Java設計模式
- 設計模式學習-使用go實現裝飾模式設計模式Go
- 學習筆記-設計模式:MVC模式筆記設計模式MVC
- 設計模式第三講-裝飾者模式設計模式
- Head First 設計模式(3)----裝飾者模式設計模式
- SpringBoot實踐設計模式———裝飾者模式Spring Boot設計模式
- 設計模式——裝飾模式設計模式
- 設計模式-裝飾模式設計模式
- 設計模式學習筆記設計模式筆記
- 學習筆記-設計模式筆記設計模式
- 一起來學習設計模式:裝飾器模式設計模式