观察者模式定义
定义:Observer模式定义对象间的一对多的依赖关系,当一个对象(被观察者)的状态发生改变时, 所有依赖于它的对象(观察者)都得到通知并被自动更新,有时候观察者模式也被称为发布/订阅模式。
观察者模式主要包涵两个部分:
- observer 观察者,为所有的具体观察者定义一个接口,在得到主题通知时更新自己
- Observable 被观察者, 观察者随着被观察者的变化更新自己。
为什么要用观察者模式
- 被观察者只需要知道观察者是谁,不需要知道两者之间具体的内容
- 被观察者如果发生变化,就会立即通知观察者更新,只有通知和响应的处理
- 一个观察者可以观察多个主题(多个被观察者),一个被观察者也可能有多个观察者,可以自由选择
- 观察者可以通过被观察的变化随时做出响应
观察者模式特点
观察者模式所做的工作其实就是在接触耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
实例
首先是简单的观察者模式使用
这里我们先设计场景,人和天气吧,根据天气的变化通知主人的出行工具
这里我们模仿一个点击事件获取edittext的内容,如果是大雪就选择地铁出门一个观察者的抽象接口,含有更新数据的方法
/**
* Created by melo on 2017/2/21.
*/
public interface People {
void upData(String string);
}
具体的人,这里给一个实体类小明,通过update方法得到结果
/**
* Created by melo on 2017/2/21.
*/
public class XiaoMing implements People {
@Override
public void upData(String string) {
if ("大雪".equals(string)){
Log.i("tag","今天大雪,建议地铁出行");
}else if ("多云".equals(string)){
Log.i("tag","今天多云,建议步行出门");
}else if ("小雨".equals(string)){
Log.i("tag","今天小雨,建议公交出门");
}
}
}
下面就是模拟被观察者,也就是天气
/**
* Created by melo on 2017/2/21.
*/
public class Weather {
private String weatherDetails;
private People mPeople;
public Weather(People people) {
this.mPeople = people;
}
public String getWeatherDetails() {
return weatherDetails;
}
public void setWeatherDetails(String weatherDetails) {
this.weatherDetails = weatherDetails;
//通知观察者数据改变
this.notifyObserver(weatherDetails);
}
public void notifyObserver(String string) {
mPeople.upData(string);
}
}
放上mainactivity,也很简单
/**
* 简单观察者模式实例
*/
public class MainActivity extends AppCompatActivity{
EditText mEditText;
Button mButton;
TextView mTextView;
Weather weather;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.et_input);
mButton = (Button) findViewById(R.id.btn_chang);
mTextView = (TextView) findViewById(R.id.tv_newweather);
XiaoMing xiaoMing=new XiaoMing();
weather = new Weather(xiaoMing);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String newWeather = mEditText.getText().toString();
Log.i("tag", "newWeather:" + newWeather);
weather.setWeatherDetails(newWeather);
}
});
}
}
接下来就不妨来测试一下输出的结果吧。
通过上面的例子可以了解到观察者模式其实也不是很难吧,下面就用更深入的实例来学习观察者模式。
首先我们分析总共需要几部分组成:
1.我们需要一个subject类,可翻译为主题或抽象通知者
/**
* Created by melo on 2017/2/21.
* subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现,
* 它把所以对观察者对象的引用保存在一个聚焦里,每个主题都可以有任何数量的观察者。
* 抽象主题提供一个接口,可以增加和删除观察者对象
*/
abstract class Subject {
private List<Observer> mObservers = new LinkedList<>();
//添加观察者
public void addObserver(Observer observer) {
mObservers.add(observer);
}
//删除观察者
public void deleteObserver(Observer observer) {
mObservers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : mObservers) {
observer.upDate();
}
}
}
2.有了subject抽象通知类,我们就需要为所有观察者定义一个接口类,用来更新自己
/**
* Created by melo on 2017/2/21.
* 抽象观察者,为所有具体观察者定义一个接口,得到主题的通知时更新自己。这个接口叫做更新接口
*
*/
public interface Observer {
void upDate();
}
3.创建一个ConcreteSubject存入观察者对象的状态
/**
* Created by melo on 2017/2/21.
* 叫做具体主题或具体通知者,将有关状态存入具体观察者对象
*/
public class ConcreteSubject extends Subject {
//具体被观察者的状态
private String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
4.到这里我们就可以创建具体的观察者
/**
* Created by melo on 2017/2/21.
* 具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态一致。
*/
public class ConcreteObserver implements Observer {
private String name;
private String observerState;
private ConcreteSubject subject;
public ConcreteObserver(String name, ConcreteSubject subject) {
this.name = name;
this.subject = subject;
}
@Override
public void upDate() {
observerState = subject.getSubjectState();
Log.i("tag", "name:" + name + ",observerState:" + observerState);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ConcreteSubject getSubject() {
return subject;
}
public void setSubject(ConcreteSubject subject) {
this.subject = subject;
}
}
5.现在在mainactivity中运行,并看一看输出的结果
//观察者模式
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConcreteSubject concreteSubject=new ConcreteSubject();
ConcreteObserver observer=new ConcreteObserver("观察者1",concreteSubject);
concreteSubject.addObserver(observer);
ConcreteObserver observer2=new ConcreteObserver("观察者2",concreteSubject);
concreteSubject.addObserver(observer2);
concreteSubject.setSubjectState("心情很好");
concreteSubject.notifyObservers();
}
}
参考来源
- 大话设计模式
- Android开发艺术探索