观察者模式

本文介绍了观察者设计模式在游戏角色状态(HP, MP)实时更新和气象数据展示中的应用,解决了代码冗余与开闭原则问题。通过Subject和Observer接口,实现了角色状态与多个面板的解耦,提高代码可维护性和扩展性。
摘要由CSDN通过智能技术生成

观察者设计模式的引入:
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类图
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值