实验一:行为型设计模式之观察模式
一、实验目的
熟练使用JAVA实现行为型设计模式-观察模式,分析观察走模式的实现原理,通过实例学习如何编程实现观察者模式,并且理解观察者模式在java事件处理中的应用。
二、实验内容
1、在某多人联机对战游戏中,多个玩家可以加入同一战队组成联盟,但战队中的某一成员受到敌人攻击时将给所有起的盟友发送通知,盟友收到通知后将作出响应。
试使用观察者模式设计并实现的过程,以实现战队成员之间的联动。
2、微信公众号与微信订阅者的故事,公众号负责推送消息,并且有取消关注和关注,普通微信号是关注公众号,并且公众推出的内容可以更新,可以取消关注。
三、实验步骤
实例1的结构图如图所示:
实例2的结构图如图所示:
第一个实例具体代码如下:
1、AllyControlCenter.java
package a.Observer.game;
import java.util.*;
public abstract class AllyControlCenter{
protected String allyName;
protected ArrayList <Observer> players = new ArrayList <Observer>();
public void setAllyName(String allyName) {
this.allyName = allyName;
}
public String getAllyName() {
return this.allyName;
}
public void join(Observer obs) {
System.out.println(obs.getName()+"加入"+this.allyName+"战队!");
players.add(obs);
}
public void quit(Observer obs) {
System.out.println(obs.getName()+"退出"+this.allyName+"战队!");
players.remove(obs);
}
public abstract void notifyObserver(String name);
}
2、Client.java
package a.Observer.game;
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);
player1.beAttacked(acc);
}
}
3、ConcreteAllyControlCenter
package a.Observer.game;
public class ConcreteAllyControlCenter extends AllyControlCenter{
public ConcreteAllyControlCenter(String allyName) {
System.out.println(allyName+"战队组建成功!");
System.out.println("-------------------------");
this.allyName = allyName;
}
public void notifyObserver(String name) {
System.out.println(this.allyName+"战队紧急通知,盟友"+name+"遭受敌人攻击。");
for(Object obs :players) {
if(!((Observer)obs).getName().equalsIgnoreCase(name)) {
((Observer)obs).help();
}
}
}
}
4、Observer.java
package a.Observer.game;
public interface Observer {
public String getName();
public void setName(String name);
public void help();
public void beAttacked(AllyControlCenter acc);
}
5、Player.java
package a.Observer.game;
public class Player implements Observer{
private String name;
public Player(String name) {
this.name=name;
}
public void setName(String name) {
this.name=name;
}
public String getName() {
return this.name;
}
public void help() {
System.out.println("坚持住,"+this.name+"来救你!");
}
public void beAttacked(AllyControlCenter acc) {
System.out.println(this.name+"被攻击!");
acc.notifyObserver(name);
}
}
运行结果如下:
第二个实例具体代码如下:
1、Observer.java
package a.Observer.winxin;
public interface Observer {
public abstract void update(String message);
}
2、Subject.java
package a.Observer.winxin;
public interface Subject {
public abstract void registerObserver(Observer observer);
public abstract void removeObserver(Observer observer);
public abstract void notifyObserver(String message);
}
3、Test.java
package a.Observer.winxin;
public class test {
public static void main(String[] args) {
Weixinusers user1=new Weixinusers();
Weixinusers user2=new Weixinusers();
Weixinusers user3=new Weixinusers();
user1.setName("User1");
user2.setName("User2");
user3.setName("user3");
WeiXinSubject su1=new WeiXinSubject();
su1.setName("电子与信息工程分院");
WeiXinSubject su2=new WeiXinSubject();
su2.setName("机电工程分院");
WeiXinSubject su3=new WeiXinSubject();
su3.setName("土木建筑工程分院");
user1.subscribeSubject(su1);
user1.subscribeSubject(su2);
user2.subscribeSubject(su2);
user3.subscribeSubject(su3);
su1.setMessage("2019体育课开始选课了!");
su1.notifyObserver(su1.getMessage());
su2.setMessage("电信分院体育课选课名单公布");
su2.notifyObserver(su2.getMessage());
su3.setMessage("电信分院体育课选课名单公布");
su3.notifyObserver(su3.getMessage());
}
}
4、WeiXinSubject.java
package a.Observer.winxin;
import java.util.*;
public class WeiXinSubject implements Subject{
private String message,name;
private List<Observer> ob=new ArrayList<Observer>();
public void setName(String name)
{
this.name=name;
}
public String getName() {
return this.name;
}
public void setMessage(String message)
{
this.message=message;
}
public String getMessage() {
return this.message;
}
public void registerObserver(Observer observer) {
if(ob.contains(observer))
return;
else
ob.add(observer);
}
public void removeObserver(Observer observer) {
ob.remove(observer);
}
public void notifyObserver(String message) {
for(Observer o:ob)
o.update(this.message);
}
}
5、Weixinusers.java
package a.Observer.winxin;
import java.util.*;
public class Weixinusers implements Observer{
private String name;
private List<Subject> users=new ArrayList<Subject>();
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
public void update(String message)
{
System.out.println("公众号推送了消息:"+message);
}
public void subscribeSubject(Subject sub)
{
if(users.contains(sub))
return;
else
{
users.add(sub);
System.out.println(this.name+":关注"+((WeiXinSubject)sub).getName()+"公众号成功!");
for(Subject u:users)
u.registerObserver(this);
}
}
public void deleSubject(Subject sub)
{
users.remove(sub);
sub.removeObserver(this);
}
}
四、实验结果分析
1 观察者模式的设计意图
2 观察者模式的结构
在观察者模式结构图中包含如下几个角色:
● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
● ConcrertObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。
观察者模式描述了如何建立对象与对象之间的依赖关系,以及如何构造满足这种需求的系统。观察者模式包含观察目标和观察者两类对象,一个目标可以有任意数目的与之相依赖的观察者,一旦观察目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将监视观察目标的状态以使其状态与目标状态同步,这种交互也称为发布-订阅(Publish-Subscribe)。观察目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。
3 观察者模式的优点
1、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。
由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
2、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,
4 观察者模式的缺点
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
3、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
4、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
欢迎您关注我的微信公众号:学习微站(studysth)
本文使用 文章同步助手 同步