设计模式是门很高深的学问,刚开始看的时候感觉就是前辈们总结出的:让代码的的书写更为简便,解偶,以及重用性比较好.
现在发现一个设计好的模式,在接口,OO上都是非常的出色.其中的心得,只可意会不可言传.
观察者模式
定义:定义对象间一对多的依赖,这样一来,当一个对象发生改变,其他依赖者会得到通知并自动更新.
举个例子:
新京报,他是一个主题,很多人都可以定购他,他不需要了解你订购他是干吗,他只知道你付了钱,他给你一份报纸,到什么地址.
如果他修改版面,他会通知你,比如说,最近物价上涨.可能需要上涨几毛钱.(有更改就会通知依赖者)
而订购他的人或者公司,属于观察者也就是依赖者,只有2个参数,一个是注册,一个是解除注册.注册后,就会收到报纸的最新消
息,一有修改就会通知你.解除注册后,你还是你,但是你已经不属于依赖者了,就不会接到相应的消息.你可以今天注册,今天解
除(这是你的事情).不会影响到其他的东西,也就是松耦合.
当2个对象之间送耦合,它们依然可以相互交互,但是彼此不知道细节.
观察者提供了一种设计模式,他让主题和观察者之间松耦合.
作为观察者,主题只知道他实现一个接口 Oberver,主题不需要知道他具体是谁,需要实现什么操作.
任何时候我们都可以增加新的观察者.因为主题实现的是一个实现oberver的抽象接口列表,所以我们可以随时增加和删除观
察者.
主题不用了解其他的,只需要给现有注册的观察者发消息就可以了,观察者的增加和改变,不需要修改主题的代码.
主题和观察者,我们可以重复使用,改变一方不会印象另外一方.
说了好多耦合方面的东西,说到底就是为了达到解耦合的目的.
看代码比较清晰
我实现了一个电脑厂商和地区代理的,一对多关系依赖.名字起的不好,里面有很多的proxy,可别认为是代理模式.
首先实现一个电脑工厂的接口
GeneralProxy.java
package com.linpyi.computer;
/**
* 电脑总代理接口
* @author work
*
*/
public interface GeneralProxy {
/**
* 注册电脑代理
* @param o
*/
public void registerComputerProxy(Observer o);
/**
* 移除电脑代理
* @param o
*/
public void removeComputerProxy(Observer o);
/**
* 更新代理价格
*/
public void notifyComputerProxy();
}
他实现了3个接口方法,注册移除和更改.
接着写观察者接口,没有多余的方法,就一个updata
package com.linpyi.computer;
/**
* 电脑观察者,自己写的代理接口
* @author work
*
*/
public interface Observer {
/**
* 更新电脑信息
* @param name 电脑品牌
* @param price 电脑价格
* @param info 电脑描述
*/
public void update(String name,float price,String info);
}
还有个代理厂商要实现的接口,也就是一个代理厂商的报价
package com.linpyi.computer;
/**
* 电脑分代理接口
* @author work
*
*/
public interface BranchProxy {
/**
* 默认方法
*/
public void display();
}
接着实现具体电脑厂商,我这使用了lenovo,不过名字打错了.
LenvoComputer.java
package com.linpyi.computer;
import java.util.ArrayList;
/**
* lenovo电脑(不好意思这lenovo写错了,暂时不改正了)
* @author work
*
*/
public class LenvoComputer implements GeneralProxy {
private ArrayList proxys ;
private String name;
private float price;
private String info;
public LenvoComputer(){
proxys = new ArrayList();
}
/**
* 更改lenvo分代理的信息
*/
public void notifyComputerProxy() {
// TODO Auto-generated method stub
for(int i = 0 ;i<proxys.size();i++){
Observer proxy = (Observer)proxys.get(i);
proxy.update(name, price, info);
}
}
/**
* 设置lenvo的电脑价格和信息
* @param name 电脑名称
* @param price 电脑价格
* @param info 电脑描述信息
*/
public void setLenvo(String name,float price,String info){
this.name=name;
this.price=price;
this.info=info;
notifyComputerProxy();
}
/**
* 注册lenvo代理
*/
public void registerComputerProxy(Observer o) {
// TODO Auto-generated method stub
proxys.add(o);
}
/**
* 移除lenvo代理
*/
public void removeComputerProxy(Observer o) {
// TODO Auto-generated method stub
int i = proxys.indexOf(o);
if(i>=0){
proxys.remove(o);
}
}
}
里面的代码应该不会很难,很容易看的懂的,
接着该实现中国区代理 lenovo了,这里要记的实现的是自己写的observer,因为JDK有默认的observer,底下介绍
package com.linpyi.computer;
/**
* 中国地区代理类,使用自己写的代理接口
* @author
*
*/
public class ChinaProxy implements BranchProxy, Observer {
private GeneralProxy generalProxy;
private String name ;
private float price;
private String info;
public ChinaProxy(GeneralProxy generalProxy){
this.generalProxy=generalProxy;
generalProxy.registerComputerProxy(this);//注册代理
}
/**
* 默认方法
*/
public void display() {
// TODO Auto-generated method stub
System.out.println("中国代理");
System.out.println("型号"+name);
System.out.println("价格"+price);
System.out.println("描述信息"+info);
}
/**
* 更新方法
*/
public void update(String name, float price, String info) {
// TODO Auto-generated method stub
this.name=name;
this.price=price;
this.info=info;
display();
}
}
一个代理不够,来2个吧
package com.linpyi.computer;
/**
* 日本代理,使用自己写的代理接口
*
* @author work
*
*/
public class JapanProxy implements BranchProxy, Observer {
private String name;
private String info;
private float price;
private GeneralProxy generalProxy;
public JapanProxy(GeneralProxy generalProxy) {
this.generalProxy = generalProxy;
generalProxy.registerComputerProxy(this);
}
public void update(String name, float price, String info) {
// TODO Auto-generated method stub
this.name = name;
this.price = price;
this.info = info;
display();
}
public void display() {
// TODO Auto-generated method stub
System.out.println("日本代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
看如何使用了
package com.linpyi.computer;
public class Client {
public static void main(String[] args){
//使用自己写的观察模式方法
LenvoComputer lenvo = new LenvoComputer();
ChinaProxy chinaProxy = new ChinaProxy(lenvo);
JapanProxy japanProxy = new JapanProxy(lenvo);
lenvo.setLenvo("lenvo0001", 10000, "disk 160G , memory 2G");
}
}
看看,我们只需要改变lenovo场商的报价
不管是中国还是日本代理,价格也就改变了
中国代理
型号lenvo0001
价格10000.0
描述信息disk 160G , memory 2G
日本代理
型号lenvo0001
价格10000.0
描述信息disk 160G , memory 2G
然后我们需要修改中国代理的其他什么东西,压根就不会影响到厂家,厂家只负责给代理人发报价和基本信息
其实代码不是很难,主要是思想,如何能真正的面向接口,面向对象编程,
JDK里面有自带的类实现观察者模式,在java.util.Observable,注意这是类而不是接口,类有类的局限性,因为JAVA只能继承
一个类,所以如果你的类有继承了实现起来就比较麻烦了.当然局限性不只这一个地方.
既然JDK有自己的Obervable,我们就从写一个电脑厂商吧,HP吧,也不错的电脑
package com.linpyi.computer;
import java.util.Observable;
/**
* HP电脑代理,使用的是JDK自带的观察者模式类(Observable)
* @author work
*
*/
public class HpComputer extends Observable {
private String name;
private float price;
private String info;
public void measurementsChanged(){
setChanged();//观察者类里的方法,主要用于开关
notifyObservers();//继承类里的方法(通知观察者)
}
public void setMeasurements(String name,float price,String info){
this.name=name;
this.price=price;
this.info=info;
measurementsChanged();
}
public String getName(){
return name;
}
public float getPrice(){
return price;
}
public String getInfo(){
return info;
}
}
记着这里是实现JDK自带的,别弄混了,里面使用的方法都是已经写好的,只是引用
notifyObservers()不说 ,就是通知观察者
setChanged()其实就是一个开关
setChanged(){
changed=true;
}
notifyObservers(Object arg){
if(changed){
//something
}
changed=false;
}
motifyObservers(){
motifyObservers(null);
}
加了一个开关,就会让通知观察者更有弹性,你可以自己设置条件,让他通知观察者,比如几分钟一次,还是什么..这里不做介绍
接着写代理地区,中国日本写完了,就写棒子吧
package com.linpyi.computer;
import java.util.Observable;
import java.util.Observer;
import com.linpyi.weather.WeatherDataOther;
/**
* 韩国代理,使用的是JDK自带的接口(Observer)
* @author work
*
*/
public class KoreaProxy implements Observer, BranchProxy {
private Observable observable;
private String name;
private String info;
private float price;
public KoreaProxy(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof HpComputer) {
HpComputer computer = (HpComputer) o;
this.name = computer.getName();
this.price = computer.getPrice();
this.info = computer.getInfo();
display();
}
}
public void display() {
// TODO Auto-generated method stub
System.out.println("韩国代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
这里实现的Observer接口也是JDK自带的
加个印度的.
package com.linpyi.computer;
import java.util.Observable;
import java.util.Observer;
/**
* 印度电脑代理(使用JDK自带的接口)
* @author work
*
*/
public class IndiaProxy implements Observer, BranchProxy {
private Observable observable;
private String name;
private String info;
private float price;
public IndiaProxy(Observable observable) {
this.observable = observable;
observable.addObserver(this);//增加观察者(JDK自带的)
}
/**
* 更新方法,使用的是JDK自带的方法
*/
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof HpComputer) {
HpComputer computer = (HpComputer) o;
this.name = computer.getName();
this.price = computer.getPrice();
this.info = computer.getInfo();
display();
}
}
public void display() {
// TODO Auto-generated method stub
System.out.println("印度代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
OK,完成了,
测试一下吧
package com.linpyi.computer;
public class Client {
public static void main(String[] args){
//使用自己写的观察模式方法
LenvoComputer lenvo = new LenvoComputer();
ChinaProxy chinaProxy = new ChinaProxy(lenvo);
JapanProxy japanProxy = new JapanProxy(lenvo);
lenvo.setLenvo("lenvo0001", 10000, "disk 160G , memory 2G");
//使用JDK的观察模式方法
HpComputer hp = new HpComputer();
KoreaProxy koreaProxy = new KoreaProxy(hp);
IndiaProxy IndiaProxy = new IndiaProxy(hp);
hp.setMeasurements("hp0001", 12000, "disk 250G , memory 2G");
}
}
运行结果
中国代理
型号lenvo0001
价格10000.0
描述信息disk 160G , memory 2G
日本代理
型号lenvo0001
价格10000.0
描述信息disk 160G , memory 2G
印度代理
型号hp0001
价格12000.0
描述信息disk 250G , memory 2G
韩国代理
型号hp0001
价格12000.0
描述信息disk 250G , memory 2G
达到的效果一样吧,
看仔细了,真的一样吗
其实看看2个运行的顺序,其实是相反的.难道有错,其实谁都没错,只是计算的方法不一样.
但是如果我们依赖了他们的顺序,就是我们错了,错误的顺序导致错误的结果.
以下引用
java.util.Observable的黑暗面
如同你发现的.可观察者是一个类而不是一个接口,更糟糕的是,他甚至没有实现一个接口.不幸的是,java.util.Observable的实现有许多的问题,限制了她的使用和复用.这并不是说他没提供有用的功能,我们只是提醒大家注意一些事实.
Observable 是一个类
首先,因为Observable是一个类.你必须设计一个类继承他,如果某类想同时具有Observable类和另外一个超类的行为,你就会陷入两难,JAVA不支持多重继承.这限制了Observable的复用能力.
再者,因为没有Observable接口,所有无法建立自己的实现.和JAVA内置的ObserverAPI搭配使用,也无法将java.util的实现换成另外一套做法.
Observable将关键的方法保护起来
看了ObservableAPI,你会发现setChanged()方法被保护起来,意味着,除非你继承自Observable,否则你无法创建Observable实例并组合到你自己的对象里来.这个设计违反了第二个设计原则:"多用组合,少用继承"
其实观察者模式差不多已经了解了,主要的写法就这些.
当然不在乎怎么写,在乎你怎么想,主要还是思维上要有面向接口和面向对象的思维,面向接口是门很深的学问
介绍一本设计模式的书<Head.First.设计模式.中文版>
很想发到论坛上,结果发现好象没发成功,郁闷,算 了
分享到:
相关推荐
观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动或发布-...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件驱动的系统或者...
结合微信公众号讲解观察者模式,生动形象,关键是上手快啊
观察者模式(Observer Pattern)是行为设计模式的一种,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心思想是发布-订阅模型,其中...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它在C++中的应用广泛且实用。这种模式的核心思想是“主体”(Subject)与“观察者”(Observer)之间的松耦合关系,允许一个对象(即主体)的状态...
c++设计模式-行为型模式-观察者模式;qt工程;c++简单源码; 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式...
观察者模式,也称为发布-订阅模式或事件驱动模式,是一种行为设计模式,它定义了对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 在C#、ASP.NET等.NET框架中,...
总结来说,观察者模式是一种重要的设计模式,它允许对象在状态改变时自动通知其他对象,从而降低了系统各部分之间的耦合度,提高了代码的灵活性和可扩展性。在实际项目中,正确使用观察者模式可以有效地管理组件间的...
在给定的“设计模式--观察者 c++版本”中,我们主要关注的是观察者模式(Observer Pattern)在C++语言中的实现。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件驱动的系统或者...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动编程或者...
观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。该模式适用于需要在对象间建立动态的、松散耦合的关系的...
观察者模式(Observer Pattern)是其中一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 在Java中,观察者模式通常通过`java.util....
观察者模式是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这个模式在很多场景下都有广泛的应用,例如事件处理、...
观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以及时地在对象之间传播状态变化。在Java中,观察者模式常用于构建事件驱动系统,使得多个对象能够监听并响应某个对象的状态改变。 首先,我们要理解...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在iOS开发中尤其常见,因为...
Java设计模式中的观察者模式(Observer Pattern)是一种对象行为型模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于事件处理和实时...
观察者模式,也被称为发布-订阅模式或事件驱动模式,是软件设计模式中的一种行为模式。这个模式的主要目的是在对象之间建立一种松散耦合的关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并...
观察者模式(Observer)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式在C++中广泛应用,特别是在需要...