通過進(jìn)銷存分析
比如 XX 超市枚碗,采購(gòu)部門要采購(gòu) IBM 型號(hào)的電腦了东揣,它是根據(jù)什么來決定采購(gòu)的呢揩页?
- 銷售情況罢维。銷售部門要反饋銷售情況,暢銷就多采購(gòu)拒逮,滯銷就不采購(gòu)磅甩;
-?庫(kù)存情況糊识。即使是暢銷產(chǎn)品玷氏,庫(kù)存都有 1000 臺(tái)了堵未,每天才賣出去 10 臺(tái),還要采購(gòu)嗎盏触?
- 采購(gòu)渗蟹。在特殊情況下,比如一個(gè)企業(yè)客戶一下子要賣 100 臺(tái)電腦赞辩,你庫(kù)存里自由 80 臺(tái)拙徽,怎么辦?催采購(gòu)部門趕快采購(gòu)呀
從以上分析來看诗宣,這三個(gè)模塊都是有自己的行為,并且與其他模塊之間的行為產(chǎn)生關(guān)聯(lián)關(guān)系
進(jìn)銷存類圖:
Purchase 負(fù)責(zé)采購(gòu)管理想诅,buyIBMComputer 是指定了采購(gòu) IBM 電腦召庞,refuseBuyIBM 是不再采購(gòu) IBM 了
public class Purchase {
????//采購(gòu)IBM型號(hào)的電腦
????public void buyIBMcomputer(int number){
????????//訪問庫(kù)存
????????Stock stock = new Stock();
????????//訪問銷售
????????Sale sale = new Sale();
????????//電腦的銷售情況
????????int saleStatus = sale.getSaleStatus();
????????if(saleStatus>80){ //銷售情況良好
????????????System.out.println("采購(gòu)IBM電腦:"+number + "臺(tái)");
????????????stock.increase(number);
????????}else{ //銷售情況不好
????????????int buyNumber = number/2; //折半采購(gòu)
????????????System.out.println("采購(gòu)IBM電腦:"+buyNumber+ "臺(tái)");
????????}
????}
????//不再采購(gòu)IBM電腦
????public void refuseBuyIBM(){
????????System.out.println("不再采購(gòu)IBM電腦");
????}
}
Purchase 定義了采購(gòu)電腦的一個(gè)標(biāo)準(zhǔn),如果銷售情況比較好来破,大于 80 分篮灼,你讓我采購(gòu)多少我就采購(gòu)多少;銷售情況不好徘禁,你讓我采購(gòu) 100 臺(tái)诅诱,我就采購(gòu) 50 臺(tái),對(duì)折采購(gòu)送朱。電腦采購(gòu)?fù)戤吜四锏矗隙ㄒ诺綆?kù)房中干旁,因此要調(diào)用庫(kù)存的方法,增加庫(kù)存電腦數(shù)量炮沐。
庫(kù)房 Stock 類:
public class Stock {
????//剛開始有100臺(tái)電腦
????private static int COMPUTER_NUMBER =100;
????//庫(kù)存增加
????public void increase(int number){
????????COMPUTER_NUMBER = COMPUTER_NUMBER + number;
????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);
????}
????//庫(kù)存降低
????public void decrease(int number){
????????COMPUTER_NUMBER = COMPUTER_NUMBER - number;
????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);
????}
????//獲得庫(kù)存數(shù)量
????public int getStockNumber(){
????????return COMPUTER_NUMBER;
????}
????//存貨壓力大了争群,就要通知采購(gòu)人員不要采購(gòu),銷售人員要盡快銷售
????public void clearStock(){
????????Purchase purchase = new Purchase();
????????Sale sale = new Sale();
????????System.out.println("清理存貨數(shù)量為:"+COMPUTER_NUMBER);
????????//要求折價(jià)銷售
????????sale.offSale();
????????//要求采購(gòu)人員不要采購(gòu)
????????purchase.refuseBuyIBM();
????}
}
庫(kù)房中的貨物數(shù)量肯定有增加和減少了大年,同時(shí)庫(kù)房還有一個(gè)容量顯示换薄,達(dá)到一定的容量后就要求對(duì)一些商品進(jìn)行折價(jià)處理,騰出更多的空間容納新產(chǎn)品翔试,于是就有了 clearStock 方法轻要,既然是清倉(cāng)處理肯定就要折價(jià)銷售了,于是在 Sale 這個(gè)類中就有了 offSale 方法垦缅。
Sale 源代碼:
public class Sale {
????//銷售IBM型號(hào)的電腦
????public void sellIBMComputer(int number){
????????//訪問庫(kù)存
????????Stock stock = new Stock();
????????//訪問采購(gòu)
????????Purchase purchase = new Purchase();
????????if(stock.getStockNumber()<number){ //庫(kù)存數(shù)量不夠銷售
????????????purchase.buyIBMcomputer(number);
????????}
????????System.out.println("銷售IBM電腦"+number+"臺(tái)");
????????stock.decrease(number);
????}
????//反饋銷售情況,0——100之間變化冲泥,0代表根本就沒人賣,100代表非常暢銷失都,出一個(gè)賣一個(gè)
????public int getSaleStatus(){
????????Random rand = new Random(System.currentTimeMillis());
????????int saleStatus = rand.nextInt(100);
????????System.out.println("IBM電腦的銷售情況為:"+saleStatus);
????????return saleStatus;
????}
????//折價(jià)處理
????public void offSale(){
????????//庫(kù)房有多少賣多少
????????Stock stock = new Stock();
????????System.out.println("折價(jià)銷售IBM電腦"+stock.getStockNumber()+"臺(tái)");
????}
}
Sale 類中的 getSaleStatus 是獲得銷售情況柏蘑,這個(gè)當(dāng)然要出現(xiàn)在 Sale 類中了,記住恰當(dāng)?shù)念惙诺角‘?dāng)?shù)念愔写馀樱N售情況當(dāng)然只有銷售人員才能反饋出來了咳焚,通過百分制的機(jī)制衡量銷售情況。
public class Client {
????public static void main(String[] args) {
????????//采購(gòu)人員采購(gòu)電腦
????????System.out.println("------采購(gòu)人員采購(gòu)電腦--------");
????????Purchase purchase = new Purchase();
????????purchase.buyIBMcomputer(100);
????????//銷售人員銷售電腦
????????System.out.println("\n------銷售人員銷售電腦--------");
????????Sale sale = new Sale();
????????sale.sellIBMComputer(1);
????????//庫(kù)房管理人員管理庫(kù)存
????????System.out.println("\n------庫(kù)房管理人員清庫(kù)處理--------");
????????Stock stock = new Stock();
????????stock.clearStock();
????}
}
場(chǎng)景類中模擬了三種人員類型的活動(dòng):采購(gòu)人員采購(gòu)電腦庞溜,銷售人員銷售電腦革半,庫(kù)管員管理庫(kù)存,運(yùn)行結(jié)果如下:
------采購(gòu)人員采購(gòu)電腦--------
IBM 電腦的銷售情況為:95
采購(gòu) IBM 電腦:100 臺(tái)
庫(kù)存數(shù)量為:200
------銷售人員銷售電腦--------
銷售 IBM 電腦 1 臺(tái)
庫(kù)存數(shù)量為:199
------庫(kù)房管理人員清庫(kù)處理--------
清理存貨數(shù)量為:199
折價(jià)銷售 IBM 電腦 199 臺(tái)
不再采購(gòu) IBM 電腦
迪米特法則教育我們“每個(gè)類只和朋友類交流”流码,這個(gè)朋友類可不是越多越好又官,越多耦合性越大,改一個(gè)對(duì)象而要修改一片對(duì)象漫试,這可不是面向?qū)ο笤O(shè)計(jì)所期望的六敬,而且這還是就三個(gè)模塊的情況,比較簡(jiǎn)單的一個(gè)小項(xiàng)目驾荣,如果有十個(gè)八個(gè)這樣的模塊是不是就要歇菜了外构,我們把進(jìn)銷存擴(kuò)充一下,如下圖的情況:
星型網(wǎng)絡(luò)拓?fù)渲忻總€(gè)計(jì)算機(jī)通過交換機(jī)和其他計(jì)算機(jī)進(jìn)行數(shù)據(jù)交換播掷,各個(gè)計(jì)算機(jī)之間并沒有直接出現(xiàn)交互的情況审编,結(jié)構(gòu)簡(jiǎn)單,而且穩(wěn)定歧匈,只要中間那個(gè)交換機(jī)不癱瘓垒酬,整個(gè)網(wǎng)絡(luò)就不會(huì)發(fā)生大的故障,公司和網(wǎng)吧一般都采用星型網(wǎng)絡(luò),那也說明星型拓?fù)涫巧畹妹裥目本浚俏覀儊硐胂胧遣皇强梢园堰@種星型結(jié)構(gòu)引入到我們的設(shè)計(jì)中呢矮湘?
加入了一個(gè)中介者作為三個(gè)模塊的交流核心,每個(gè)模塊之間不再相互交流乱顾,要交流就通過中介者進(jìn)行板祝,每個(gè)模塊只負(fù)責(zé)自己的業(yè)務(wù)邏輯,不屬于自己的則丟給中介者來處理.
建立了兩個(gè)抽象類 AbstractMediator 和 AbstractColeague走净,每個(gè)對(duì)象只是與中介者 Mediator 之間產(chǎn)生依賴券时,與其他對(duì)象之間沒有直接的關(guān)系,AbstractMediator 的作用是把中介者的抽象定義伏伯。
public abstract class AbstractMediator {
????protected Purchase purchase;
????protected Sale sale;
????protected Stock stock;
????//構(gòu)造函數(shù)
????public AbstractMediator(){
????????purchase = new Purchase(this);
????????sale = new Sale(this);
????????stock = new Stock(this);
????}
????//中介者最重要的方法橘洞,叫做事件方法,處理多個(gè)對(duì)象之間的關(guān)系
????public abstract void execute(String str,Object...objects);
}
我們?cè)賮砜淳唧w的中介者说搅,中介者可以根據(jù)業(yè)務(wù)的要求產(chǎn)生多個(gè)中介者(一般情況只有一個(gè)中介者)
public class Mediator extends AbstractMediator {
????//中介者最重要的方法
????public void execute(String str,Object...objects){
????????if(str.equals("purchase.buy")){ //采購(gòu)電腦
????????????this.buyComputer((Integer)objects[0]);
????????}else if(str.equals("sale.sell")){ //銷售電腦
????????????this.sellComputer((Integer)objects[0]);
????????}else if(str.equals("sale.offsell")){ //折價(jià)銷售
????????????this.offSell();
????????}else if(str.equals("stock.clear")){ //清倉(cāng)處理
????????????this.clearStock();
????????}
????}
????//采購(gòu)電腦
????private void buyComputer(int number){
????????int saleStatus = super.sale.getSaleStatus();
????????if(saleStatus>80){ //銷售情況良好
????????????System.out.println("采購(gòu)IBM電腦:"+number + "臺(tái)");
????????????super.stock.increase(number);
????????}else{ //銷售情況不好
????????????int buyNumber = number/2; //折半采購(gòu)
????????????System.out.println("采購(gòu)IBM電腦:"+buyNumber+ "臺(tái)");
????????}
????}
????//銷售電腦
????private void sellComputer(int number){
????????if(super.stock.getStockNumber()<number){ //庫(kù)存數(shù)量不夠銷售
? ??????????super.purchase.buyIBMcomputer(number);
????????}
? ??????super.stock.decrease(number);
? ? }
? ??//折價(jià)銷售電腦
????private void offSell(){
????????System.out.println("折價(jià)銷售IBM電腦"+stock.getStockNumber()+"臺(tái)");
????}
????//清倉(cāng)處理
????private void clearStock(){
????????//要求清倉(cāng)銷售
????????super.sale.offSale();
????????//要求采購(gòu)人員不要采購(gòu)
????????super.purchase.refuseBuyIBM();
????}
}
中介者 Mediator 有定義了多個(gè) Private 方法炸枣,其目標(biāo)是處理各個(gè)對(duì)象之間的依賴關(guān)系,即是說把原有一個(gè)對(duì)象要依賴多個(gè)對(duì)象的情況移到中介者的 Private 方法中實(shí)現(xiàn)弄唧,在實(shí)際項(xiàng)目中适肠,一般的做法是中介者按照職責(zé)進(jìn)行劃分,每個(gè)中介者處理一個(gè)或多個(gè)類似的關(guān)聯(lián)請(qǐng)求候引。
AbstractColleague 源碼:
public abstract class AbstractColleague {
????protected AbstractMediator mediator;
????public AbstractColleague(AbstractMediator _mediator){
????????this.mediator = _mediator;
????}
}
采購(gòu)類 Purchase 的源碼如下:
public class Purchase extends AbstractColleague{
????public Purchase(AbstractMediator _mediator){
????????super(_mediator);
????}
????//采購(gòu)IBM型號(hào)的電腦
????public void buyIBMcomputer(int number){
????????super.mediator.execute("purchase.buy", number);
????}
????//不在采購(gòu)IBM電腦
????public void refuseBuyIBM(){
????????System.out.println("不再采購(gòu)IBM電腦");
????}
}
Purchase 類是不是簡(jiǎn)化了很多侯养,看著也清晰了很多,處理自己的職責(zé)澄干,與外界有關(guān)系的事件處理則交給了中介者來完成.
Stock 類:
public class Stock extends AbstractColleague {
????public Stock(AbstractMediator _mediator){
????????super(_mediator);
????}
????//剛開始有100臺(tái)電腦
????private static int COMPUTER_NUMBER =100;
????//庫(kù)存增加
????public void increase(int number){
????????COMPUTER_NUMBER = COMPUTER_NUMBER + number;
????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);
????}
????//庫(kù)存降低
????public void decrease(int number){
????????COMPUTER_NUMBER = COMPUTER_NUMBER - number;
????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);
????}
????//獲得庫(kù)存數(shù)量
????public int getStockNumber(){
????????return COMPUTER_NUMBER;
????}
????//存貨壓力大了逛揩,就要通知采購(gòu)人員不要采購(gòu),銷售人員要盡快銷售
????public void clearStock(){
????????System.out.println("清理存貨數(shù)量為:"+COMPUTER_NUMBER);
????????super.mediator.execute("stock.clear");
????}
}
Sale 類的源碼:
public class Sale extends AbstractColleague {
????public Sale(AbstractMediator _mediator){
????????super(_mediator);
????}
????//銷售IBM型號(hào)的電腦
????public void sellIBMComputer(int number){
????????super.mediator.execute("sale.sell", number);
????????System.out.println("銷售IBM電腦"+number+"臺(tái)");
????}
????//反饋銷售情況,0——100之間變化麸俘,0代表根本就沒人賣辩稽,100代表非常暢銷,出1一個(gè)賣一個(gè)
????public int getSaleStatus(){
????????Random rand = new Random(System.currentTimeMillis());
????????int saleStatus = rand.nextInt(100);
????????System.out.println("IBM電腦的銷售情況為:"+saleStatus);
????????return saleStatus;
????}
????//折價(jià)處理
????public void offSale(){
????????super.mediator.execute("sale.offsell");
????}
}
再來看場(chǎng)景類的變化
public class Client {
????public static void main(String[] args) {
????????AbstractMediator mediator = new Mediator();
????????//采購(gòu)人員采購(gòu)電腦
????????System.out.println("------采購(gòu)人員采購(gòu)電腦--------");
????????Purchase purchase = new Purchase(mediator);
????????purchase.buyIBMcomputer(100);
????????//銷售人員銷售電腦
????????System.out.println("\n------銷售人員銷售電腦--------");
????????Sale sale = new Sale(mediator);
????????sale.sellIBMComputer(1);
????????//庫(kù)房管理人員管理庫(kù)存
????????System.out.println("\n------庫(kù)房管理人員清庫(kù)處理--------");
????????Stock stock = new Stock(mediator);
????????stock.clearStock();
????}
}
在場(chǎng)景類中增加了一個(gè)中介者从媚,然后分別傳遞到三個(gè)同事類中逞泄,三個(gè)類都具有相同的特性:只負(fù)責(zé)處理自己的活動(dòng)(行為),與自己無關(guān)的活動(dòng)就丟給中介者處理拜效,從項(xiàng)目設(shè)計(jì)上來看炭懊,加入了中介者,設(shè)計(jì)結(jié)構(gòu)清晰了很多拂檩,而且類間的耦合性大大減少,代碼質(zhì)量也有了很大的提升嘲碧。
通用類圖為:
從類圖中看稻励,中介者模式有以下幾部分組成:
抽象中介者(Mediator)角色:抽象中介者角色定義統(tǒng)一的接口用于各同事角色之間的通信。
具體中介者(Concrete Mediator)角色:具體中介者角色通過協(xié)調(diào)各同事角色實(shí)現(xiàn)協(xié)作行為,因此它必須依賴于各個(gè)同事角色望抽。
同事(Colleague)角色:每一個(gè)同事角色都知道中介者角色加矛,而且與其他的同事角色通信的時(shí)候,一定要通過中介者角色協(xié)作煤篙。每個(gè)同事類的行為分為兩種:一種是同事本身的行為斟览,比如改變對(duì)象本身的狀態(tài),處理自己的行為等等辑奈,這種方法叫做自發(fā)行為(Self-Method)苛茂,與其他的同事類或中介者沒有任何的依賴;第二種是是必須依賴中介者才能完成的行為鸠窗,叫做依賴方法(Dep-Method)妓羊。