sincerit 观察者模式(Observer Pattern)

目标(Subject)即观察者观察的对象
观察者(Observer)

观察者模式:主要特点是对象之间是一对多的依赖关系,每当目标(subject)的状态发生改变时,其相关的观察者(observer)做出相应的行为
观察者模式:由一个Subject抽象目标类,ConcreteSubject具体目标类,Observer抽象观察者,ConcreteObserver具体观察者组成
观察者模式:是23种设计模式之一,也是使用频率最高的设计模式之一,是一种行为型模式
观察者模式:实质是目标(Subject)类聚合(当成成员)一个观察者的列表(list),并且有增删的方法,以及一个notify()通知函数和一个状态量state,当状态量改变时目标(Subject)发送通知告诉观察者,观察者列表的观察者改变行为(obs.update())

观察者模式结构图:
在这里插入图片描述
图片来源: https://www.cnblogs.com/renhui/p/6479748.html

观察者模式有两种方法通知观察者状态发生改变:

  1. 推模式:通知观察者状态改变时,把状态传给观察者 obs.update(state),再根据何种状态做出相应行为;
  2. 拉模式:目标聚合观察者的同时,观察者也把观察目标对象(Subject)当成成员,当通知观察者状态改变时,观察者通过subject得到状态(getState()),再根据state做出相应行为
    推模式和拉模式的区别结构图中就是ConcreteSubject和ConcreteObserver是否有联系(上图的是拉模式)

观察者模式所包含的类:
Subject:抽象目标类,把具体目标类抽象出来便于扩展其他具体目标类,该类包含一个观察者列表,对列表的处理方法(增删…),最重要的要有notify()通知方法
Observer:抽象观察者类,对具体观察者类做抽象,因为观察者有很多不同类型的观察者,把这些观察者共有的放放到抽象类,公共的有update()方法
ConcreteSubject:具体目标类,继承Subject,本身有一个状态量,状态改变就发送通知,通知观察者(至于观察者做出什么行为就管不着了,只是通知做出行为)
ConcreteObserver:具体观察者类,根据通知做出相应的行为 obs.update()
Client:客户端类,负责创建目标类及观察者类并调用通知函数

由于观察者模式的使用频率很频繁,JDK对观察者模式的支持,提供了Observerable类和Observer接口,Observerable相当于抽象目标类(Subject) ,Observer是抽象观察者。

JDK提供的Observerable类及Observer接口结构图
在这里插入图片描述
图片来源:https://www.cnblogs.com/renhui/p/6479748.html
考虑到推模式和拉模式,所以有update(Observerable o, Object arg)会传递一个目标做参数,并且考虑到通知的信息会很复杂,就封装成一个对象Object

软件公司欲开发一款多人联机对战游戏(类似魔兽世界、星际争霸等游戏),在该游戏中,多个玩家可以加入同一战队组成联盟,当战队中某一成员受到敌人攻击时将给所有其他盟友发送通知,盟友收到通知后将作出响应。
解决方案(结构图):
在这里插入图片描述
图片来源: https://www.cnblogs.com/renhui/p/6479748.html
实现代码:

抽象目标类

import java.util.ArrayList; 
// 注意这里是自己实现Observer不可以到Observer的包

abstract class AllyControlCenter {
   protected String allyName;
   // 聚合一个Observer队列
   protected ArrayList<Observer> players = new ArrayList<Observer>();
   
   public void setAllyName(String name) {
	   this.allyName = name;
   }
   
   public String  getAllyName() {
	   return allyName;
   }
   
   // 添加observer的方法
   public void join(Observer obs) {
	   System.out.println(obs.getName() + "加入" + this.allyName + "战队");
	   players.add(obs);
   }
   
   // 删除observer的方法
   public void quit(Observer obs) {
	   System.out.println(obs.getName() + "退出" + this.allyName + "战队");
	   players.remove(obs);
   }
   
   public abstract void notifyObserver(String name);
}

具体目标类

public class ConcreteAllyControlCenter extends AllyControlCenter {

	public ConcreteAllyControlCenter(String name) {
		System.out.println(name + "战队组建成功");
		this.allyName = name;
	}

	// 具体目标类实现具体的通知方法
	@Override
	public void notifyObserver(String name) {
		System.out.println(this.allyName+"紧急通知:" + name + "遭受敌人攻击");
		for (Object obs : players) { // 集合是不会记住元素的类型的
			if (!((Observer)obs).getName().equalsIgnoreCase(name)) {
				((Observer)obs).help();
			}
		}
	}
}

观察者抽象(接口)类

public interface Observer {
   public String getName();
   public void setName(String name);
   public void help(); // 观察者救援别人的方法
   public void beAttacked(AllyControlCenter acc); // 被攻击发送消息给目标类
}

具体观察者类

public class Player implements Observer {
	private String name; // 观察者的名字
	public Player(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	// 具体观察者实现救援方法
	@Override
	public void help() {
		System.out.println(name + "前来救援");
	}

    // 观察者被攻击,通知战队控制中心,控制中心通知其他盟友来救援
	@Override
	public void beAttacked(AllyControlCenter acc) {
		System.out.println(name+"被攻击");
		acc.notifyObserver(name);
	}

}

客户端类

public class Client {

	public static void main(String[] args) {
		AllyControlCenter acc;
		acc = new ConcreteAllyControlCenter("金庸群侠"); 
		
		Observer player1, player2, player3, player4;
		player1 = new Player("杨过");
		acc.join(player1);
		player2 = new Player("令狐冲");
		acc.join(player2);
		player3 = new Player("张无忌");
		acc.join(player3);
		player4 = new Player("段誉");
		acc.join(player4);
		
		// 遭受攻击
		player2.beAttacked(acc);
	}
}

观察者类总结:
待续。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值