龙空技术网

Java之观察者模式(Observer)

树下魅狐 82

前言:

而今咱们对“java观察者模式代码”大概比较关注,朋友们都需要知道一些“java观察者模式代码”的相关资讯。那么小编同时在网上汇集了一些关于“java观察者模式代码””的相关文章,希望看官们能喜欢,小伙伴们一起来了解一下吧!

1. 设计意图

定义对象之间的一对多依赖关系,以便当一个对象更改状态时,将自动通知和更新其所有依赖项。

简而言之

你别来找我,给我你的联系方式,有事我会主动联系你

2.案例演示

以当前最火热的吃鸡游戏作为一个简单的案例来演示观察者模式,当玩家进入游戏时,会收到游戏服务器推送的提示消息,随着游戏的进行,如果某个玩家被Kill掉了,游戏服务器会把此消息推送给房间里的其他玩家。在本案例中,“游戏” 是一个抽象的被观察者,“吃鸡游戏” 是具体的被观察者;“游戏玩家”是一个抽象的观察者(接口),而玩家A、玩家B等是具体的观察者。案例的UML关系如下图:

3. 示例代码

3.1 抽象的被观察者类(Subject)

AbstractGame.java

package com.ramostear.pattern.observer;import java.util.ArrayList;/** * @author ramostear * @create-time 2019/1/5 0005-23:27 * @modify by : * @info:[抽象的被观测者类] * @since: */public abstract class AbstractGame { /** * 定义一个存放观察者的容器 */ public final ArrayList<Observer> obsList = new ArrayList<>(); /** * 注册观察者 * @param obs 观察者 * @param <T> */ public <T> void attach(Observer obs){ if (obs == null){ throw new NullPointerException("Observer is null."); }else{ this.attachObs(obs); } } /** * 注册观察者 * @param obs */ private void attachObs(Observer obs){ if (obs == null){ throw new NullPointerException("class is null"); }else { synchronized (obsList){ if(!obsList.contains(obs)){ obsList.add(obs); } } } } /** * 注销观察者 * @param obs 观察者 * @param <T> */ public <T> void detach(Observer obs){ if(obs == null){ throw new NullPointerException("Observer is null"); }else { this.detachObs(obs); } } /** * 注销观察者 * @param obs */ private void detachObs(Observer obs){ if(obs == null){ throw new NullPointerException("Class is null"); }else{ synchronized (obsList){ obsList.remove(obs); } } } /** * 通知所有的观察者 * @param messages */ public abstract void notifyAllObs(String...messages); /** * 通知某个观察者 * @param obs * @param messages */ public abstract void notifyObs(Observer obs,String...messages);}

AbstractGame类中定义了添加、删除和通知观察者的方法,同时有一个List类型的容器,用于保存已注册的观察者,当需要通知观察者时,从容器中取出观察者信息。

说明:抽象的被观察者可以定义成一个抽象类或者接口,本案例中采用的是抽象类

3.2 抽象的观察者接口(Observer)

Observer.java

package com.ramostear.pattern.observer;/** * @author ramostear * @create-time 2019/1/5 0005-23:26 * @modify by : * @info:[观察者接口] * @since: */public interface Observer { /** * 更新状态 * @param messages */ void update(String... messages);}

在该接口中定义了一个update() 方法,当被观察者发出通知时,此方法会被调用。

3.3 具体被观察者(ConcreteSubject)

ChikenGame继承了AbstractGame类,并对通知方法进行了具体的实现。

ChikenGame.java

package com.ramostear.pattern.observer;/** * @author ramostear * @create-time 2019/1/5 0005-23:55 * @modify by : * @info:[吃鸡游戏类] * @since: */public class ChickenGame extends AbstractGame { private String roomName; public ChickenGame(String roomName) { this.roomName = roomName; } public String getRoomName() { return roomName; } public void setRoomName(String roomName) { this.roomName = roomName; } @Override public void notifyAllObs(String... messages) { obsList.forEach(obs->{ this.notifyObs(obs,messages); }); } @Override public void notifyObs(Observer obs, String... messages) { if (obs == null){ throw new NullPointerException("Observer is null"); }else{ obs.update(messages); } }}

3.4 具体观察者(ConcreteObserver)

Gamer类实现了Observer接口,并对Observer的update方法进行了具体的实现;这里为了演示,只是简单的对消息进行输出。

Gamer.java

package com.ramostear.pattern.observer;/** * @author ramostear * @create-time 2019/1/6 0006-0:06 * @modify by : * @info:[游戏玩家] * @since: */public class Gamer implements Observer{ private String name; public Gamer(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void update(String... messages) { System.out.println("玩家:"+name); for (String message:messages){ System.out.println("消息->"+message+"\n"); } }}

3.5 测试本次案例

创建一个吃鸡游戏叫“三国吃鸡演义” ,将刘、关、张三个玩家注册到吃鸡游戏中。游戏发布消息给三个玩家,刘、关、张同时收到游戏发出的消息,当关羽挂掉后,只有刘、张两个玩家收到消息;当张飞再挂掉后,只有刘备收到消息。为了演示观察者模式,最后我们让关羽满血复活,此时刘、关二人收到游戏发出的消息。

App.java

package com.ramostear.pattern.observer;/** * @author ramostear * @create-time 2019/1/6 0006-0:08 * @modify by : * @info:[测试类] * @since: */public class App { public static void main(String[] args){ ChickenGame game = new ChickenGame("三国吃鸡演义"); Gamer gamerLiu = new Gamer("刘备"); Gamer gamerZhang = new Gamer("张飞"); Gamer gamerGuan = new Gamer("关羽"); game.attach(gamerLiu); game.attach(gamerGuan); game.attach(gamerZhang); game.notifyAllObs("欢迎进入"+game.getRoomName()); game.notifyAllObs(new String[]{"刘关张桃园三结义,开始三国吃鸡演义..."}); game.detach(gamerGuan); game.notifyAllObs("#关羽:\"我去!被98K爆了,快来扶我一下!\""); game.notifyAllObs("#刘备:\"我去,这货肥得一批!\""); game.detach(gamerZhang); game.notifyAllObs("#张飞:\"我去,这比是挂!\""); game.notifyAllObs("#刘备:\"我去!咋这么多人,我凉了!\""); game.attach(gamerGuan); game.notifyAllObs("关羽满血复活"); game.notifyAllObs("#刘备:\"苟住,苟住就能赢!\""); }}

测试结果:

4. 适用性

当满足以下情况中的一种时使用观察者模式

当抽象有两个Aspect时,一个依赖于另一个。 将这些Aspact封装在单独的对象中可让您独立地改变和重用它们.当一个对象的更改需要更改其他对象时,你不知道到底需要更改多少个关联的对象当不希望多个对象之前发生紧耦合时

5. 真实案例

java.util.Observerjava.util.EventListenerjavax.servlet.http.HttpSessionBindingListener

标签: #java观察者模式代码 #java观察者模式代码怎么写的出来