设计模式--观察者设计模式
定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
java提供Obeservable类和Observer接口。
比如购房,购房者是观察者,而房价是被观察者,房价的变化是被观察者所关注的。
/** * 被观察者 * @author soyoungboy * */ public class House extends Observable { //房价 private float price; public House(float price) { this.price = price; } public float getPrice() { return price; } public void setPrice(float price) { //设置变化点 super.setChanged(); //通知观察者,价格发生变化 super.notifyObservers(price); this.price = price; } @Override public String toString() { return "House [price=" + price + "]"; } }
/** * 房价观察者 * @author soyoungboy * */ public class HouseObserver implements Observer { //购房者名称 private String name; public HouseObserver(String name) { this.name = name; } @Override public void update(Observable o, Object arg) { if (arg instanceof Float) { System.out.println("name 观察到房价变化为:"+((Float)arg).floatValue()); } } }
public class Test { public static void main(String[] args) { House house = new House(10000); HouseObserver houseObserver = new HouseObserver("购房者A"); HouseObserver houseObserver1 = new HouseObserver("购房者B"); HouseObserver houseObserver2 = new HouseObserver("购房者C"); //添加房价的监听者 house.addObserver(houseObserver); house.addObserver(houseObserver1); house.addObserver(houseObserver1); System.out.println(house.toString()); house.setPrice(20000); System.out.println(house.toString()); house.setPrice(30000); System.out.println(house.toString()); } }
结果为:
House [price=10000.0] name 观察到房价变化为:20000.0 name 观察到房价变化为:20000.0 House [price=20000.0] name 观察到房价变化为:30000.0 name 观察到房价变化为:30000.0 House [price=30000.0]
观察者模式在android编码过程中的使用
比如网络状态的变化,每个activity都有链接网络的操作,当网络状态发生变化的使用,应该通过通知所有涉及到网络操作的activity网络状态的变化,并且能够根据网络状态不同进行不同的处理,比如2G,3G网络下,不进行网络图片的加载,而在wifi网络的情况下进行加载:下面是thinkandroid里面实现网络状态监听的观察者模式的使用:
TANetChangeObserver -- 观察者
TANetworkStateReceiver.registerObserver()--为添加新的观察者
notifyObserver() -- 为通知所有的观察者网络状态的变化
registerObserver(),removeRegisterObserver ()--添加观察者,删除观察者对象
public class TANetworkStateReceiver extends BroadcastReceiver { private static final String TAG = "TANetworkStateReceiver"; private static Boolean networkAvailable = false; private static netType netType; private static ArrayList<TANetChangeObserver> netChangeObserverArrayList = new ArrayList<TANetChangeObserver>(); private final static String ANDROID_NET_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; public final static String TA_ANDROID_NET_CHANGE_ACTION = "ta.android.net.conn.CONNECTIVITY_CHANGE"; private static BroadcastReceiver receiver; private static BroadcastReceiver getReceiver() { if (receiver == null) { receiver = new TANetworkStateReceiver(); } return receiver; } @Override public void onReceive(Context context, Intent intent) { receiver = TANetworkStateReceiver.this; if (intent.getAction().equalsIgnoreCase(ANDROID_NET_CHANGE_ACTION) || intent.getAction() .equalsIgnoreCase(TA_ANDROID_NET_CHANGE_ACTION)) { Logger.i(TAG, "网络状态改变."); if (!TANetWorkUtil.isNetworkAvailable(context)) { Logger.i(TAG, "没有网络连接."); ToastUtil.toasts(context, "网络断开,请检查网络"); networkAvailable = false; } else { Logger.i(TAG, "网络连接成功."); ToastUtil.toastL(context, "网络连接成功"); netType = TANetWorkUtil.getAPNType(context); networkAvailable = true; } notifyObserver(); } } /** * 注册网络状态广播 * * @param mContext */ public static void registerNetworkStateReceiver(Context mContext) { IntentFilter filter = new IntentFilter(); filter.addAction(TA_ANDROID_NET_CHANGE_ACTION); filter.addAction(ANDROID_NET_CHANGE_ACTION); mContext.getApplicationContext() .registerReceiver(getReceiver(), filter); } /** * 检查网络状态 * * @param mContext */ public static void checkNetworkState(Context mContext) { Intent intent = new Intent(); intent.setAction(TA_ANDROID_NET_CHANGE_ACTION); mContext.sendBroadcast(intent); } /** * 注销网络状态广播 * * @param mContext */ public static void unRegisterNetworkStateReceiver(Context mContext) { if (receiver != null) { try { mContext.getApplicationContext().unregisterReceiver(receiver); } catch (Exception e) { // TODO: handle exception // TALogger.d("TANetworkStateReceiver", e.getMessage()); Logger.i(TAG, e.getMessage()); } } } /** * 获取当前网络状态,true为网络连接成功,否则网络连接失败 * * @return */ public static Boolean isNetworkAvailable() { return networkAvailable; } public static netType getAPNType() { return netType; } private void notifyObserver() { for (int i = 0; i < netChangeObserverArrayList.size(); i++) { TANetChangeObserver observer = netChangeObserverArrayList.get(i); if (observer != null) { if (isNetworkAvailable()) { /* observer.onConnect(netType); */ observer.onConnect(netType); } else { observer.onDisConnect(); } } } } /** * 注册网络连接观察者 * * @param observerKey observerKey */ public static void registerObserver(TANetChangeObserver observer) { if (netChangeObserverArrayList == null) { netChangeObserverArrayList = new ArrayList<TANetChangeObserver>(); } netChangeObserverArrayList.add(observer); } /** * 注销网络连接观察者 * * @param resID observerKey */ public static void removeRegisterObserver(TANetChangeObserver observer) { if (netChangeObserverArrayList != null) { netChangeObserverArrayList.remove(observer); } } }
检测网络改变的观察者:
public class TANetChangeObserver { /** * 网络连接连接时调用 */ public void onConnect(netType type) { } /** * 当前没有网络连接 */ public void onDisConnect() { } }
如下为程序中的使用方式:
1 TANetworkStateReceiver.registerObserver(new TANetChangeObserver() 2 { 3 @Override 4 public void onConnect(netType type) 5 { 6 // TODO Auto-generated method stub 7 super.onConnect(type); 8 Toast.makeText(TestActivity.this, "onConnect", 9 Toast.LENGTH_SHORT).show(); 10 } 11 12 @Override 13 public void onDisConnect() 14 { 15 // TODO Auto-generated method stub 16 super.onDisConnect(); 17 Toast.makeText(TestActivity.this, "onDisConnect", 18 Toast.LENGTH_SHORT).show(); 19 } 20 });
最后这段代码其实是可以放到BaseActivity中对所有Activity界面进行控制的,每个页面中的网络状态其实都可以通过这种方式进行统一管理,有添加观察者,也要在生命周期里面及时删除观察者。
2015年12月20日20:55:37
观察者模式在android源码中的使用(读《android source design pattern analysis & pratice》)
BaseAdapter中使用了观察者设计模式:
BaseAdapter里面有注册观察者和解除观察者的操作以及通知所有观察者的notifyDateSetChange()代码.
部分分析的博客:http://www.cnblogs.com/izhanjun/p/4183788.html
Mr.simple的博客:http://blog.csdn.net/bboyfeiyu/article/details/44040533
还有就是BroadCastReceiver也是观察者模式:
通过map存储BroadcastReceiver,key封装广播的信息类,当发布广播通过AMS到这个map中查询注册了这个广播的IntentFilter的BroadCastReveiver,然后通过ReceiverSpipather将广播分发给订阅对象。
观察者模式的适用场景就是一个类发生变化,需要将消息传递到相关很多类的时候。