1.觀察者模式概念
當(dāng)一個(gè)對(duì)象存在一對(duì)多的關(guān)系的時(shí)候画髓,則可以使用觀察者模式(Observer Pattern)独令。比如来庭,當(dāng)一個(gè)對(duì)象發(fā)生改變的時(shí)候宣决,所以依賴這個(gè)對(duì)象的對(duì)象都會(huì)接收到通知。觀察者模式屬于行為型模式吆你。
2.觀察者模式作用
定義對(duì)象間的一種一對(duì)多的依賴關(guān)系弦叶,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新妇多。
3.何時(shí)使用
一個(gè)對(duì)象(目標(biāo)對(duì)象)的狀態(tài)發(fā)生改變伤哺,所有的依賴對(duì)象(觀察者對(duì)象)都將得到通知,進(jìn)行廣播通知。
4.優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn)
1)觀察者和被觀察者是抽象耦合的立莉。
2)建立一套觸發(fā)機(jī)制绢彤。
缺點(diǎn)
3)如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間蜓耻。
4)如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話茫舶,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰刹淌。
5)觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的饶氏,而僅僅只是知道觀察目標(biāo)發(fā)生了變化。
5.例子解析
抽象觀察者:
public interface Observer {
public void update(Object object);
}
具體觀察者:
具體觀察者一:
public class OberverOne implements Observer{
@Override
public void update(Object object) {
Weather weather = (Weather) object;
System.out.println("OberverOne檢測(cè)到氣候改變================");
System.out.println("OberverOne--溫度:"+weather.getTemperatrue());
System.out.println("OberverOne--氣壓:"+weather.getPressure());
System.out.println("OberverOne--濕度:"+weather.getHumidity());
}
}
具體觀察者二:
public class OberverTwo implements Observer{
@Override
public void update(Object object) {
Weather weather = (Weather) object;
System.out.println("OberverTwo檢測(cè)到氣候改變================");
System.out.println("OberverTwo--溫度:"+weather.getTemperatrue());
System.out.println("OberverTwo--氣壓:"+weather.getPressure());
System.out.println("OberverTwo--濕度:"+weather.getHumidity());
}
}
被觀察者(主題):
可以看到有勾,這里并沒(méi)有按照類圖將被觀察者設(shè)計(jì)為一個(gè)接口嚷往,Java JDK也提供觀察者模式接口,java.util.Observable就是被觀察者柠衅,這個(gè)類也沒(méi)有被設(shè)計(jì)為一個(gè)接口皮仁,而是一個(gè)類。雖然在設(shè)計(jì)模式中菲宴,為了實(shí)現(xiàn)程序可拓展贷祈,易維護(hù),通常建議多用組合喝峦,少用繼承势誊,但這只是一個(gè)理論,要根據(jù)具體情況使用設(shè)計(jì)模式谣蠢,只要滿足需求粟耻,我們又何必多做功夫。而且《Head First Design Patterns》中也說(shuō)到了眉踱,書(shū)中提到的設(shè)計(jì)模式挤忙,多多少少會(huì)有違背設(shè)計(jì)模式原則的地方。
public class Observed {
private ArrayList<Observer> observers = new ArrayList<Observer>();
public boolean attach(Observer observer) {
return observers.add(observer);
}
public boolean remove(Observer observer)
{
return observers.remove(observer);
}
public void notifyAllObservers(Object object) {
for (Observer observer : observers) {
observer.update(object);
}
}
}
繼承了被觀察者的具體類:
public class WeatherData extends Observed {
private Weather weather;
public WeatherData() {
weather = new Weather();
}
public void measureNotifyChanged() {
notifyAllObservers(weather);
}
public void setMeasureElement(float temperatrue, float humidity,
float pressure) {
this.weather.setTemperatrue(temperatrue);
this.weather.setHumidity(humidity);
this.weather.setPressure(pressure);
measureNotifyChanged();
}
}
數(shù)據(jù)實(shí)體:
public class Weather {
private float temperatrue;
private float humidity;
private float pressure;
public float getTemperatrue() {
return temperatrue;
}
public void setTemperatrue(float temperatrue) {
this.temperatrue = temperatrue;
}
public float getHumidity() {
return humidity;
}
public void setHumidity(float humidity) {
this.humidity = humidity;
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure;
}
}
客戶端:
public class Test {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
OberverOne oberverOne = new OberverOne();
OberverTwo oberverTwo = new OberverTwo();
weatherData.attach(oberverOne);
weatherData.attach(oberverTwo);
while (true) {
System.out.println("請(qǐng)選擇模式 1.設(shè)置監(jiān)聽(tīng) 2.改變數(shù)據(jù)");
Scanner scanner = new Scanner(System.in);
String temp = scanner.next();
if (temp.equals("1")) {
int temp2 = scanner.nextInt();
if (temp2 == 1) {
if (weatherData.attach(oberverOne)) {
System.out.println("OberverOne監(jiān)聽(tīng)成功谈喳!");
}else
System.out.println("OberverOne監(jiān)聽(tīng)失敳崃摇!");
}else if (temp2 == -1) {
if (weatherData.remove(oberverOne)) {
System.out.println("OberverOne取消監(jiān)聽(tīng)成功婿禽!");
}else
System.out.println("OberverOne取消監(jiān)聽(tīng)失斏蜕!");
}else if (temp2 == 2) {
if (weatherData.attach(oberverOne)) {
System.out.println("OberverTwo監(jiān)聽(tīng)成功扭倾!");
}else
System.out.println("OberverTwo監(jiān)聽(tīng)失數砹恪!");
}else if (temp2 == -2) {
if (weatherData.remove(oberverOne)) {
System.out.println("OberverTwo取消監(jiān)聽(tīng)成功膛壹!");
}else
System.out.println("OberverTwo取消監(jiān)聽(tīng)失敿葜小琼牧!");
}
}else if (temp.equals("2")) {
System.out.println("請(qǐng)輸入溫度,氣壓哀卫,濕度:");
float temperatrue = scanner.nextFloat();
float humidity = scanner.nextFloat();
float pressure = scanner.nextFloat();
weatherData.setMeasureElement(temperatrue, pressure, humidity);
}
}
}
}
6.調(diào)用JDK內(nèi)部觀察者例子
觀察者就沒(méi)什么好說(shuō)的了,直接實(shí)現(xiàn)java.util.Obserser接口,重寫(xiě)update()方法即可:
public class CurrentConditionDisplay implements Observer {
private Weather weather;
public CurrentConditionDisplay() {
}
public void display(Weather weather) {
System.out.println("Current condition: "+weather.getTemperatrue()+"F degree and humidity: "+weather.getHumidity()+"% humidity");
}
public void update(Observable o, Object arg) {
weather = (Weather) arg;
this.display(weather);
}
}
被觀察者除了繼承java.util.Observable撬槽,還需要做兩個(gè)步驟:
1)先調(diào)用setChange(),標(biāo)記狀態(tài)已改變的事實(shí)此改。
2)然后調(diào)用兩個(gè)notifyObserver中的一個(gè):
public class WeatherData extends Observable {
private Weather weather;
public WeatherData() {
weather = new Weather();
}
@Override
public void notifyObservers(Object arg) {
// TODO Auto-generated method stub
super.notifyObservers(weather);
}
public void measureNotifyChanged()
{
this.setChanged();
notifyObservers();
}
public void setMeasureElement(float temperatrue,float humidity,float pressure)
{
this.weather.setTemperatrue(temperatrue);
this.weather.setHumidity(humidity);
this.weather.setPressure(pressure);
measureNotifyChanged();
}
}
詳細(xì)代碼可以通過(guò)文章結(jié)尾提供的地址下載源碼,查看項(xiàng)目下的com.lgy.test.four包的內(nèi)容侄柔。
notifyObserver()或notifyObserver(Object object)
7.總結(jié)
設(shè)計(jì)模式六大原則:
1共啃、開(kāi)閉原則(Open Close Principle)
開(kāi)閉原則的意思是:對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉暂题。在程序需要進(jìn)行拓展的時(shí)候移剪,不能去修改原有的代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果薪者。簡(jiǎn)言之纵苛,是為了使程序的擴(kuò)展性好,易于維護(hù)和升級(jí)言津。想要達(dá)到這樣的效果攻人,我們需要使用接口和抽象類,后面的具體設(shè)計(jì)中我們會(huì)提到這點(diǎn)悬槽。
2怀吻、里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向?qū)ο笤O(shè)計(jì)的基本原則之一。 里氏代換原則中說(shuō)初婆,任何基類可以出現(xiàn)的地方蓬坡,子類一定可以出現(xiàn)。LSP 是繼承復(fù)用的基石磅叛,只有當(dāng)派生類可以替換掉基類屑咳,且軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用弊琴,而派生類也能夠在基類的基礎(chǔ)上增加新的行為乔宿。里氏代換原則是對(duì)開(kāi)閉原則的補(bǔ)充。實(shí)現(xiàn)開(kāi)閉原則的關(guān)鍵步驟就是抽象化访雪,而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn)详瑞,所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。
3臣缀、依賴倒轉(zhuǎn)原則(Dependence Inversion Principle)
這個(gè)原則是開(kāi)閉原則的基礎(chǔ)坝橡,具體內(nèi)容:針對(duì)接口編程,依賴于抽象而不依賴于具體精置。
4计寇、接口隔離原則(Interface Segregation Principle)
這個(gè)原則的意思是:使用多個(gè)隔離的接口,比使用單個(gè)接口要好。它還有另外一個(gè)意思是:降低類之間的耦合度番宁。由此可見(jiàn)元莫,其實(shí)設(shè)計(jì)模式就是從大型軟件架構(gòu)出發(fā)、便于升級(jí)和維護(hù)的軟件設(shè)計(jì)思想蝶押,它強(qiáng)調(diào)降低依賴踱蠢,降低耦合。
5棋电、迪米特法則茎截,又稱最少知道原則(Demeter Principle)
最少知道原則是指:一個(gè)實(shí)體應(yīng)當(dāng)盡量少地與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對(duì)獨(dú)立赶盔。
6企锌、合成復(fù)用原則(Composite Reuse Principle)
合成復(fù)用原則是指:盡量使用合成/聚合的方式,而不是使用繼承于未。
原則畢竟是理論撕攒,很多時(shí)候要根據(jù)具體情況來(lái)使用這些原則,不要生搬硬套烘浦,強(qiáng)迫一定要符合這個(gè)原則打却,不要忘了最初的目的,我們只是為了讓程序更好維護(hù)罷了谎倔。
8.源碼下載
http://download.csdn.net/detail/lgywsdy/9748282