麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

行為型設(shè)計(jì)模式

2019-11-15 01:03:09
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
行為型設(shè)計(jì)模式

行為型設(shè)計(jì)模式概述

行為模式關(guān)注的是對(duì)象的行為。該類(lèi)型的模式需要做的是對(duì)可能變化的行為進(jìn)行抽象,通過(guò)封裝達(dá)到整個(gè)架構(gòu)的可擴(kuò)展性。這些模式所要封裝的行為,恰恰是軟件架構(gòu)中最不穩(wěn)定的部分,擴(kuò)展的可能性也最大。將這些行為封裝起來(lái),利用抽象的特性,就提供了擴(kuò)展的可能。

實(shí)現(xiàn)的機(jī)制:

使用繼承機(jī)制在類(lèi)間分派行為

使用對(duì)象組合而不是繼承,它描述一組對(duì)象怎樣協(xié)作完成單個(gè)對(duì)象所無(wú)法完成的任務(wù)


(一)模板方法(TEMPLATE METHOD)模式

問(wèn)題提出:

通常我們會(huì)遇到這樣的一個(gè)問(wèn)題:我們知道一個(gè)算法或是流程所需的關(guān)鍵步聚,并確定了這些步聚的執(zhí)行順序。但是某些步聚的具體實(shí)現(xiàn)是未知的,或者是某些步聚的實(shí)現(xiàn)與具體的環(huán)境相關(guān)。

生活場(chǎng)景:

一個(gè)簡(jiǎn)單的訂單處理需求:一個(gè)客戶(hù)可以在一個(gè)訂貨單中訂購(gòu)多個(gè)貨物(也稱(chēng)為訂貨單項(xiàng)目),貨物的銷(xiāo)售價(jià)是根據(jù)貨物的進(jìn)貨價(jià)進(jìn)行計(jì)算的。有些貨物可以打折的,有些是不可以打折的。每一個(gè)客戶(hù)都有一個(gè)信用額度,每張訂單的總價(jià)不能超出該客戶(hù)的信用額度。

根據(jù)上面的業(yè)務(wù),我們可以知道處理一個(gè)訂單需要的步聚:

1. 遍歷訂貨單的訂貨單項(xiàng)目列表,累加所有貨物的總價(jià)格(根據(jù)訂貨單項(xiàng)目計(jì)算出銷(xiāo)售價(jià))

2. 根據(jù)客戶(hù)號(hào)獲得客戶(hù)的信用額度

3. 把客戶(hù)號(hào),訂單的總價(jià)格,及訂單項(xiàng)目列表寫(xiě)入到數(shù)據(jù)庫(kù)

但是我們并不能確定怎么計(jì)算出貨物的銷(xiāo)售價(jià),怎樣根據(jù)客戶(hù)號(hào)獲得客戶(hù)的信用額度及把訂單信息寫(xiě)入數(shù)據(jù)庫(kù)這些方法的具體實(shí)現(xiàn)。

模板方法模式把我們不知道具體實(shí)現(xiàn)的步聚封裝成抽象方法,提供一些按正確順序調(diào)用它們的具體方法(這些具體方法統(tǒng)稱(chēng)為模板方法),這樣構(gòu)成一個(gè)抽象基類(lèi)。子類(lèi)通過(guò)繼承這個(gè)抽象基類(lèi)去實(shí)現(xiàn)各個(gè)步聚的抽象方法,而工作流程卻由父類(lèi)來(lái)控制。

public abstract class AbstractOrder {

public Order placeOrder(int customerId , List orderItemList){

int total = 0;

for(int i = 0; i < orderItemList.size();i++){

OrderItem orderItem = (OrderItem)orderItemList.get(i);

total += getOrderItemPRice(orderItem) * orderItem.getQuantity();

}

if(total > getSpendingLimit(customerId)){

throw new BusinessException("超出信用額度" + getSpendingLimit(customerId));

}

int orderId = saveOrder(customerId, total, orderItemList);

return new OrderImpl(orderId,total);

}

public abstract int getOrderItemPrice(OrderItem orderItem);

public abstract int getSpendingLimit(int customerId);

public abstract int saveOrder(int customerId, int total, List orderItemList);

}

把不變的行為搬到超類(lèi),去除子類(lèi)中重復(fù)的代碼來(lái)體現(xiàn)他的優(yōu)勢(shì)。當(dāng)不變的和可變的行為在方法中混合在一起時(shí),不變的行為就會(huì)在子類(lèi)中重復(fù)出現(xiàn),模板方法模式就是將這些不變的行為搬移到一個(gè)超類(lèi)中,避免重復(fù)代碼。

這是一個(gè)很簡(jiǎn)單的模式,卻被非常廣泛的使用。之所以簡(jiǎn)單是因?yàn)樵谶@個(gè)模式中僅僅使用到了繼承關(guān)系。

繼承關(guān)系由于自身的缺陷,被專(zhuān)家們扣上了“罪惡”的帽子。“使用委派關(guān)(聚合)系代替繼承關(guān)系”,“盡量使用接口實(shí)現(xiàn)而不是抽象類(lèi)繼承”等等專(zhuān)家警告,讓我們這些菜鳥(niǎo)對(duì)繼承“另眼相看”。

其實(shí),繼承還是有很多自身的優(yōu)點(diǎn)所在。只是被大家濫用的似乎缺點(diǎn)更加明顯了。合理的利用繼承關(guān)系,還是能對(duì)你的系統(tǒng)設(shè)計(jì)起到很好的作用的。而模板方法模式就是其中的一個(gè)使用范例。


(二)策略(Strategy )模式

問(wèn)題提出:

在業(yè)務(wù)當(dāng)中常常出現(xiàn)一個(gè)問(wèn)題有一組算法,在不同的情況下我們有可能使用不同的算法。我們需要找到一種靈活簡(jiǎn)便的設(shè)計(jì)方式:將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類(lèi)中,從而使得它們可以相互替換。

生活場(chǎng)景:

向客戶(hù)報(bào)價(jià),對(duì)于銷(xiāo)售部門(mén)的人來(lái)講,這是一個(gè)非常復(fù)雜的問(wèn)題,對(duì)不同的客戶(hù)要報(bào)不同的價(jià)格,比如:

對(duì)普通客戶(hù)或者是新客戶(hù)報(bào)的是全價(jià);

對(duì)老客戶(hù)報(bào)的價(jià)格,根據(jù)客戶(hù)年限,給予一定的折扣;

對(duì)大客戶(hù)報(bào)的價(jià)格,根據(jù)大客戶(hù)的累計(jì)消費(fèi)金額,給予一定的折扣;

還要考慮客戶(hù)購(gòu)買(mǎi)的數(shù)量和金額,比如:雖然是新用戶(hù),但是一次購(gòu)買(mǎi)的數(shù)量非常大,或者是總金額非常高,也會(huì)有一定的折扣;

還有,報(bào)價(jià)人員的職務(wù)高低,也決定了他是否有權(quán)限對(duì)價(jià)格進(jìn)行一定的浮動(dòng)折扣;

總之,向客戶(hù)報(bào)價(jià)是非常復(fù)雜的,不同的情況銷(xiāo)售人員采取不同的策略。

publicclassPrice {

/**@paramgoodsPrice商品銷(xiāo)售原價(jià)

*@paramcustomerType客戶(hù)類(lèi)型

*@return計(jì)算出來(lái)的,應(yīng)該給客戶(hù)報(bào)的價(jià)格*/

publicdoublequote(doublegoodsPrice,String customerType){

if(customerType.equals("普通客戶(hù)")){

System.out.println("對(duì)于新客戶(hù)或者是普通客戶(hù),沒(méi)有折扣");

returngoodsPrice;

}elseif(customerType.equals("老客戶(hù)")){

System.out.println("對(duì)于老客戶(hù),統(tǒng)一折扣5%");

returngoodsPrice*(1-0.05);

}elseif(customerType.equals("大客戶(hù)")){

System.out.println("對(duì)于大客戶(hù),統(tǒng)一折扣10%");

returngoodsPrice*(1-0.1);

}

returngoodsPrice;

}

}

價(jià)格類(lèi)包含了所有計(jì)算報(bào)價(jià)的算法,使得價(jià)格類(lèi),尤其是報(bào)價(jià)這個(gè)方法比較龐雜,難以維護(hù)。 咋辦?

publicclassPrice {

publicdoublequote(doublegoodsPrice,String customerType){

if(customerType.equals("普通客戶(hù)")){

returnthis.calcPriceForNormal(goodsPrice);

}elseif(customerType.equals("老客戶(hù)")){

returnthis.calcPriceForOld(goodsPrice);

}elseif(customerType.equals("大客戶(hù)")){

returnthis.calcPriceForLarge(goodsPrice);

}

returngoodsPrice;

}

privatedoublecalcPriceForNormal(doublegoodsPrice){&hellip;}

privatedoublecalcPriceForOld(doublegoodsPrice){…}

privatedoublecalcPriceForLarge(doublegoodsPrice){…}

}

再想想,問(wèn)題還是存在,只不過(guò)從計(jì)算報(bào)價(jià)的方法挪動(dòng)到價(jià)格類(lèi)里面了,假如有100個(gè)或者更多這樣的計(jì)算方式,這會(huì)讓這個(gè)價(jià)格類(lèi)非常龐大,難以維護(hù)。而且,維護(hù)和擴(kuò)展都需要去修改已有的代碼,這是很不好的,違反了開(kāi)-閉原則。

另外:經(jīng)常會(huì)有這樣的需要,在不同的時(shí)候,要使用不同的計(jì)算方式。

比如:在公司周年慶的時(shí)候,所有的客戶(hù)額外增加3%的折扣;在換季促銷(xiāo)的時(shí)候,普通客戶(hù)是額外增加折扣2%,老客戶(hù)是額外增加折扣3%,大客戶(hù)是額外增加折扣5%。這意味著計(jì)算報(bào)價(jià)的方式會(huì)經(jīng)常被修改,或者被切換。過(guò)了促銷(xiāo)時(shí)間,又還回到正常的價(jià)格體系上來(lái)了。而現(xiàn)在的價(jià)格類(lèi)中計(jì)算報(bào)價(jià)的方法,是固定調(diào)用各種計(jì)算方式,這使得切換調(diào)用不同的計(jì)算方式很麻煩,每次都需要修改if-else里面的調(diào)用代碼。

用來(lái)解決上述問(wèn)題的一個(gè)合理的解決方案就是策略模式。

策略模式使得算法可以在不影響到客戶(hù)端的情況下發(fā)生變化。策略模式把行為和環(huán)境分開(kāi)。環(huán)境類(lèi)負(fù)責(zé)維持和查詢(xún)行為類(lèi),各種算法在具體的策略類(lèi)中提供。由于算法和環(huán)境獨(dú)立開(kāi)來(lái),算法的增減,修改都不會(huì)影響到環(huán)境和客戶(hù)端。

根據(jù)策略模式解決場(chǎng)景問(wèn)題,設(shè)計(jì)如下:

public interface Baojia {public double baojia(double price);

}

public class Content {private Baojia bj;

public Content(Baojia bj) {super();this.bj = bj;}public double daZhe(double price){return bj.baojia(price);}

}

public class LaoKeHuYear3_5 implements Baojia {

@Overridepublic double baojia(double price) {return price*.75;}

}

public class NewKenHu implements Baojia {

@Overridepublic double baojia(double price) {if(price>10000){return price*(1-0.2);}return price;}

}

public class DaKeHu implements Baojia {

@Overridepublic double baojia(double price) {return price*0.5;}

}

public class Test {public static void main(String[] args) {Baojia bj = new LaoKeHuYear3_5();Content c = new Content(bj);double p = c.daZhe(1000);System.out.println(p);}

}


(三)觀察者(Observer )模式

問(wèn)題提出:

在軟件系統(tǒng)中,我們有時(shí)需要定義一種一對(duì)多的依賴(lài)關(guān)系. 讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象, 這個(gè)主題對(duì)象在狀態(tài)發(fā)生變化的時(shí)候,會(huì)通知所有的觀察者對(duì)象,使他們能夠自動(dòng)更新自己。

生活場(chǎng)景:

網(wǎng)上商店中商品在名稱(chēng) 價(jià)格等方面有變化,如果系統(tǒng)能自動(dòng)通知會(huì)員,將網(wǎng)上商店區(qū)別傳統(tǒng)商店的一大特色.

代碼實(shí)現(xiàn):定義主題類(lèi)

public class product extends Observable{  

 private String name;  

 private float price;  

 public String getName(){

return name;

}

public void setName(String name){   

this.name=name;  

 //設(shè)置變化點(diǎn)  

  setChanged();  

  notifyObservers(name);

  }   

  public float getPrice(){

return price;

}   

public void setPrice(float price){  

  this.price=price;  

 //設(shè)置變化點(diǎn)  

  setChanged();   

notifyObservers(new Float(price));

  }

}

代碼實(shí)現(xiàn):定義觀察者

public class NameObserver implements Observer{  

 private String name=null;  

 public void update(Observable obj,Object arg){   

  if (arg instanceof String){    

  name=(String)arg;  

   System.out.println("NameObserver :name changet to "+name);  

   }

  }

}

public class PriceObserver implements Observer{  

 private float price=0;  

 public void update(Observable obj,Object arg){  

   if (arg instanceof Float){   

   price=((Float)arg).floatValue();    

   System.out.println("PriceObserver :price changet to "+price);  

   }  

 }

}

public class Test {

public static void main(String args[]){

Product product=new Product();

NameObserver nameobs=new NameObserver();

PriceObserver priceobs=new PriceObserver();

//加入觀察者

product.addObserver(nameobs);

product.addObserver(priceobs);

product.setName("橘子紅了");

product.setPrice(9.22f);   

}

}


(四)命令(Command )模式

問(wèn)題提出:

在軟件系統(tǒng)中,“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場(chǎng)合,比如要對(duì)行為進(jìn)行“記錄、撤銷(xiāo)/重做、事務(wù)”等處理,這種無(wú)法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”解耦?將一組行為抽象為對(duì)象,可以實(shí)現(xiàn)二者之間的松耦合。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产美女精品视频 | av电影在线免费 | 欧美一级三级在线观看 | 一级毛片真人免费播放视频 | 久久超| 综合日韩av | 性片免费看| 国产xxxxx在线观看 | 一区二区三区视频在线观看 | 99欧美视频 | 免费看成年人网站 | 国产精品一区二区三区在线播放 | 一级黄色影片在线观看 | 一级看片免费视频 | 久久99久久99精品 | av电影免费看 | 国产超碰人人做人人爱 | 国产一区二区三区四区五区加勒比 | 中文字幕精品在线视频 | 日本欧美一区二区三区在线观看 | 怦然心动50免费完整版 | 羞羞网站 | 成人在线观看网 | 李宗瑞国产福利视频一区 | 欧美高清第一页 | 久久久久国 | 欧美18—19sex性hd按摩 | 精品久久久一二三区播放播放播放视频 | 精品国产一区二区三区久久久蜜 | 久久精品男人 | 午夜小电影| 成人精品视频在线 | 一区二区三区日韩电影 | 又黄又爽又色无遮挡免费 | 亚洲男人的天堂在线视频 | 国产精品久久久久久久久久大牛 | 国产精品99久久久久久大便 | 蜜桃成品人免费视频 | gril hd| 国产精品刺激对白麻豆99 | jizzzxxxxhd|