观察者设计模式的引入:
1.在没有观察者模式的日子里:
有这样一个业务场景:
一个游戏中,有一个角色,角色有hp,mp,在游戏窗口中,有一些面板来显示游戏角色的hp、mp.
显示Hp的有三种显示方式:球形显示、面板框文字显示和血条显示
package Observer.a;
class Role{
private String name;
private Integer hp;
private Integer mp;
public Integer getHp() {
return hp;
}
public void setHp(Integer hp) {
this.hp = hp;
//就是在这个地方,当hp发生变化的时候,一定要通知三个地方:
//球形、血条、面板
System.out.println("血条更新hp为:" +hp);
System.out.println("球形更新hp为:"+hp);
System.out.println("面板更新hp为:"+hp);
}
public Integer getMp() {
return mp;
}
public void setMp(Integer mp) {
this.mp = mp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Monster{
public void attack(Role r) {
r.setHp(r.getHp()-10);
}
}
public class AppTest {
public static void main(String[] args) {
Role r = new Role();
r.setName("古天乐");
r.setHp(100);
r.setMp(100);
Monster m = new Monster();
m.attack(r);
}
}
变化来了,如果在游戏面板中,突然多了一个组件也需要显示角色的hp和mp,那么就要在以前的代码中,继续添加新的代码,这样不好!
1.违反了开闭原则。
2.违反了单一职责原则。
package Observer.b;
import java.util.ArrayList;
import java.util.List;
/*
* 为了解决a包中的问题,编写代码:
*/
class Role{
private String name;
private Integer hp;
private Integer mp;
private List<Observer> observers = new ArrayList<>();
public Integer getHp() {
return hp;
}
public void setHp(Integer hp) {
this.hp = hp;
//当hp发生变化,就通知所有观察者。
notifyObservers();
}
public Integer getMp() {
return mp;
}
public void setMp(Integer mp) {
this.mp = mp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Role [name=" + name + ", hp=" + hp + ", mp=" + mp + "]";
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Object obj) {
observers.remove(obj);
}
//主体对象通知所有观察者
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
interface Observer{
public void update();
}
class Panel implements Observer{
private Role r;
public Panel(Role r) {
super();
this.r = r;
}
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("在当前角色的左上角面板中更新信息为:"+r);
}
}
class BallPanel implements Observer{
private Role r;
public BallPanel(Role r) {
super();
this.r = r;
}
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("在当前角色的球形中更新信息为:"+r);
}
}
class HeadPanel implements Observer{
private Role r;
public HeadPanel(Role r) {
super();
this.r = r;
}
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("当前角色头顶中更新信息为:"+r);
}
}
class Monster{
public void attack(Role r) {
r.setHp(r.getHp()-10);
}
}
public class AppTest {
public static void main(String[] args) {
Role r = new Role();
r.setName("古天乐");
r.setHp(100);
r.setMp(100);
Observer p = new Panel(r);
Observer bp = new BallPanel(r);
Observer hp = new HeadPanel(r);
r.addObserver(p);
r.addObserver(bp);
r.addObserver(hp);
Monster m = new Monster();
m.attack(r);
}
}
此时这样写代码,问题不大。下面再列举一个观察者设计模式的典型例子。
2.观察者设计模式
在手机端和窗口中显示气象站所检测得到的相关数据。
package Observer.c;
/*
* 观察者设计模式的典型例子
*/
import java.util.ArrayList;
import java.util.List;
//该接口表示实体对象应该实现的三个方法。
interface Subject{
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyAllObservers();
}
//此类表示气象站
class WeatherStation implements Subject{
//表示空气温度
private Integer temperature;
//表示空气湿度
private Integer humidity;
//表示空气压力
private Integer pressure;
//用容器承接所有的观察者
private List<Observer> observers = new ArrayList<>();
//传感器可以感知:温度、湿度、气压,一旦感知到就给自己的属性赋值
public void setData(Integer temperature, Integer humidity, Integer pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyAllObservers();
}
public Integer getTemperature() {
return temperature;
}
public void setTemperature(Integer temperature) {
this.temperature = temperature;
}
public Integer getHumidity() {
return humidity;
}
public void setHumidity(Integer humidity) {
this.humidity = humidity;
}
public Integer getPressure() {
return pressure;
}
public void setPressure(Integer pressure) {
this.pressure = pressure;
}
//添加
public void addObserver(Observer observer) {
observers.add(observer);
}
//删除
public void removeObserver(Observer observer) {
observers.remove(observer);
}
//通知
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
interface Observer{
void update();
}
class Phone implements Observer{
private WeatherStation w;
public Phone(WeatherStation w) {
this.w = w;
//this表示当前对象
w.addObserver(this);
}
@Override
public void update() {
//此处表示网络编程
System.out.println("手机端显示大气温度为:"+w.getTemperature());
System.out.println("手机端显示大气湿度为:"+w.getHumidity());
System.out.println("手机端显示大气压力为:"+w.getPressure());
}
}
class Window implements Observer{
private WeatherStation w;
public Window(WeatherStation w) {
this.w = w;
//this表示当前对象
w.addObserver(this);
}
@Override
public void update() {
//此处表示网络编程
System.out.println("窗口显示大气温度为:"+w.getTemperature());
System.out.println("窗口显示大气湿度为:"+w.getHumidity());
System.out.println("窗口显示大气压力为:"+w.getPressure());
}
}
public class AppTest {
public static void main(String[] args) {
WeatherStation w = new WeatherStation();
Phone p = new Phone(w);
Window wd = new Window(w);
w.setData(15, 80, 47);
}
}
3.观察者设计模式的UML类图