java八大設計模式,java設計模式-Observe

 2023-12-06 阅读 17 评论 0

摘要:一、背景                     請模擬下面情形: 小孩在睡覺,醒來后要求吃東西 代碼: class Child{private boolean wakenUp = false;void wakeUp(){wakenUp = true;}public boolean isWakenUp() {return wakenUp;}public vo

一、背景                    

請模擬下面情形:
小孩在睡覺,醒來后要求吃東西
代碼:
class Child{private boolean wakenUp = false;void wakeUp(){wakenUp = true;}public boolean isWakenUp() {return wakenUp;}public void setWakenUp(boolean wakenUp) {this.wakenUp = wakenUp;}
}class Dad implements Runnable{Child c;public Dad(Child c){this.c = c;}@Overridepublic void run() {while(!c.isWakenUp()){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}feed(c);}private void feed(Child c) {System.out.println("feed child");}}public class Test {public static void main(String[] args) {Child d = new Child();new Thread(new Dad(d)).start();}}

上面代碼運行起來是有問題的,永遠等在那里,因為child永遠不會醒過來;

java八大設計模式。那么,想讓小孩5s之后醒過來怎么做?

?

二、讓小孩5s之后醒          

每一個小孩就是一個單獨的線程;
代碼:
class Child implements Runnable{private boolean wakenUp = false;void wakeUp(){wakenUp = true;}public boolean isWakenUp() {return wakenUp;}public void setWakenUp(boolean wakenUp) {this.wakenUp = wakenUp;}@Overridepublic void run() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}this.wakeUp();}
}class Dad implements Runnable{Child c;public Dad(Child c){this.c = c;}@Overridepublic void run() {while(!c.isWakenUp()){System.out.println("child is't wake up");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}feed(c);}private void feed(Child c) {System.out.println("feed child");}}public class Test {public static void main(String[] args) {Child d = new Child();new Thread(d).start();new Thread(new Dad(d)).start();}}

前端和后端的區別、console:

child is't wake up
child is't wake up
child is't wake up
child is't wake up
child is't wake up
feed child

?

這個小程序就模擬完了;也就是說要做完這個功能就已經做完了;
但是有什么不合理的地方?
小孩一直在睡著,如果采取現在這種編程模式,Dad就一直監視,無法干其他事情了,就只能在這里死死的盯著他;1s鐘盯一眼,太累了;
這個累的意思就是,CPU的資源無端的被消耗了,CPU沒事老是在這循環著;如果小孩3小時不醒就得循環3小時;這種編程的方式起碼在效率上有問題;
那么,怎么修正這個問題呢?
三、第二版的設計              
第二版的設計,不要讓Dad在這浪費時間了;
Dad是主動的檢測這個小孩有沒有醒;主動的監聽是非常消耗CPU資源的;
讓小孩醒過來的時候自己調我這方法就完了;反過來讓小孩監控他Dad;
代碼:
class Child implements Runnable{private Dad d;public Child(Dad d){this.d = d;}void wakeUp(){d.feed(this);}@Overridepublic void run() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}this.wakeUp();}
}class Dad{public void feed(Child c) {System.out.println("feed child");}
}public class Test {public static void main(String[] args) {Dad d = new Dad();Child c = new Child(d);new Thread(c).start();}}

過5s后,console打印:feed child

mvc設計模式、?

同樣的功能,這種方式比上面的要效率高一些,消耗的CPU要少一些;
但是作為設計來講,在一個軟件項目之中的設計,如果只考慮到當前這種設計不具有彈性,也就是不具有可擴展性
什么叫做沒有彈性?
比方說設計一個新聞系統,發表一篇文章需要經過三級審查,編輯審了,副主編審,再主編審;如果不符合要求或者含有反動等信息就不能發表出去;
這時候你在程序里就寫了三級,假如說將來級別增加了,需要四級審查、五級...怎么辦?改源代碼就很累;
考慮到可擴展性就可以用一個參數做配置,在配置文件里寫3就是三級審查,寫4就是四級審查....這樣就有彈性一些;
上面代碼,考慮一個問題:小孩可能會在不同的時間段醒來、不同的地點醒來,針對于不同醒來的事件,Dad的處理方式應該是不同的;這件事情的發生是包含著一些具體情況的,應該把不同的情況告訴他Dad,怎么樣把事情的各種各樣的信息告訴他Dad呢?
該用什么樣的設計方法?
四、對于事件的處理            
對于Dad來說,要根據事件的具體情況,才能做出具體的選擇,也就是說作為Child來說,有責任把這件事情的具體情況通知你的監測人;
可以這么寫,在Child里面增加什么時候醒來的時間time、醒來的地點loc,然后傳給feed()里面的child c;
可以這么寫:
class Child implements Runnable{private Dad d;String time;String loc;public Child(Dad d){this.d = d;}void wakeUp(){time = "晚上";loc = "床上";d.feed(this);}@Overridepublic void run() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}this.wakeUp();}
}class Dad{public void feed(Child c) {System.out.println("child wake up time :" + c.time);System.out.println("child wake up location :" + c.loc);System.out.println("feed child");}
}public class Test {public static void main(String[] args) {Dad d = new Dad();Child c = new Child(d);new Thread(c).start();}
}
View Code

console:5s后打印:

child wake up time :晚上
child wake up location :床上
feed child

?

但是:仔細分析,作為time它應該是小孩的屬性嗎?loc應該是小孩的屬性嗎?
不是,它們應該是事件本身的屬性;是事件發生時候的時間、地點。
所以,面向對象設計的一條最基礎的原則:最合適的屬性應該放在最合適的類里面;
所以:
1)再增加一個事件類:
2)并且,child的wakeUp()方法里面調用Dad的feed()方法,已經寫死了,假如child醒過來不想讓Dad喂他,而是讓Dad帶他出去玩呢?
那么feed方法就不合適了。更靈活的方法是:child一醒過來發出一件事,就讓Dad對這件事做出反應,只要Dad做出正確的反應就ok了。
所以feed方法換為ActionToWakenUp;

java 單例模式、?

代碼:

/*** 醒過來的事件*/
class WakenUpEvent{private long time;private String loc;private Child source;        //發生事件的源對象public WakenUpEvent(long time, String loc, Child source) {super();this.time = time;this.loc = loc;this.source = source;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getLoc() {return loc;}public void setLoc(String loc) {this.loc = loc;}public Child getSource() {return source;}public void setSource(Child source) {this.source = source;}
}class Child implements Runnable{private Dad d;public Child(Dad d){this.d = d;}void wakeUp(){d.ActionToWakenUp(new WakenUpEvent(System.currentTimeMillis(), "bed", this));}@Overridepublic void run() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}this.wakeUp();}
}class Dad{public void ActionToWakenUp(WakenUpEvent e) {System.out.println("child wake up time " + e.getTime());System.out.println("child wake up location " + e.getLoc());System.out.println("feed child");}
}public class Test {public static void main(String[] args) {Dad d = new Dad();Child c = new Child(d);new Thread(c).start();}
}

console,5s后打印:

child wake up time 1529505152384
child wake up location bed
feed child

?

?

上面的設計其實還有問題:

假如說不止Dad,小孩醒過來爺爺也要做出一點反應,該怎么辦呢?怎么樣讓更多的人對這件事做出反應?

?

?

?五、第三種設計方法          

現在問題是怎么讓監聽事件的這些個人Dad、GrandFather、奶奶,以及對事件做出響應,怎么能做到比較好的擴展,不需要在Child類里面改來改去;
因為在Child里面改的話:
不但要增加private GrandFather gf;
還需要在wakeUp方法里面增加GrandFather的ActionToWakenUp方法;
還需要修改Child的構造方法,Child(Dad d, GrandFather gf)
...
修改為如下:
import java.util.ArrayList;
import java.util.List;public class Test {public static void main(String[] args) {Child c = new Child();c.addWakenUpListener(new Dad());c.addWakenUpListener(new GrandFather());new Thread(c).start();}
}/*** 發出事件的主體*/
class Child implements Runnable{private List<WakenUpListener> WakenUplisteners = new ArrayList<WakenUpListener>();public void addWakenUpListener(WakenUpListener l){this.WakenUplisteners.add(l);}void wakeUp(){for(WakenUpListener listener : WakenUplisteners){listener.ActionToWakenUp(new WakenUpEvent(System.currentTimeMillis(), "bed", this));}}@Overridepublic void run() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}this.wakeUp();}
}//對應醒事件的監聽器接口
interface WakenUpListener {public void ActionToWakenUp(WakenUpEvent e);
}//Dad監聽器
class Dad implements WakenUpListener{public void ActionToWakenUp(WakenUpEvent e) {System.out.println("event time: "+e.getTime() +",event location: "+e.getLoc());System.out.println("feed child");}
}
//GrandFather監聽器
class GrandFather implements WakenUpListener{public void ActionToWakenUp(WakenUpEvent e) {System.out.println("event time: "+e.getTime() +",event location: "+e.getLoc());System.out.println("hug child");}
}/*** 醒事件*/
class WakenUpEvent{private long time;private String loc;private Object source;        //發生事件的源對象public WakenUpEvent(long time, String loc, Object source) {super();this.time = time;this.loc = loc;this.source = source;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getLoc() {return loc;}public void setLoc(String loc) {this.loc = loc;}public Object getSource() {return source;}public void setSource(Object source) {this.source = source;}
}

console:

event time: 1529508249412,event location: bed
feed child
event time: 1529508249413,event location: bed
hug child

?

?

轉載于:https://www.cnblogs.com/tenWood/p/9206107.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/191123.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息