设计模式之观察者模式(上)

观察者模式
1)概述
1.定义

定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

2.作用

建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。

在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。

3.结构图
4.角色

Subject(目标):目标又称为主题,指被观察的对象,在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify(),目标类可以是接口,也可以是抽象类或具体类。

ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法,如果无须扩展目标类,则具体目标类可以省略。

Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。

ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法,通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。

5.代码实现

观察者模式描述了如何建立对象与对象之间的依赖关系,以及如何构造满足这种需求的系统。

抽象目标类Subject

import java.util.*;

abstract class Subject {
  //定义一个观察者集合用于存储所有观察者对象
  protected ArrayList observers<Observer> = new ArrayList();
 
  //注册方法,用于向观察者集合中增加一个观察者
	public void attach(Observer observer) {
    observers.add(observer);
  }
 
  //注销方法,用于在观察者集合中删除一个观察者
	public void detach(Observer observer) {
    observers.remove(observer);
  }
 
  //声明抽象通知方法
	public abstract void notify();
}

具体目标类ConcreteSubject

public class ConcreteSubject extends Subject {
  //实现通知方法
	public void notify() {
    //遍历观察者集合,调用每一个观察者的响应方法
		for(Object obs:observers) {
			((Observer)obs).update();
		}
	}	
}

抽象观察者Observer

interface Observer {
  //声明响应方法
	public void update();
}

具体观察者ConcreteObserver

public class ConcreteObserver implements Observer {
  //实现响应方法
	public void update() {
		 //具体响应代码
	}
}
6.注意

在复杂的情况下,具体观察者类ConcreteObserver的update()方法在执行时需要使用到具体目标类ConcreteSubject中的状态(属性),因此在ConcreteObserver与ConcreteSubject之间有时候还存在关联或依赖关系,在ConcreteObserver中定义一个ConcreteSubject实例,通过该实例获取存储在ConcreteSubject中的状态。

2)完整解决方案
1.结构图

AllyControlCenter充当抽象目标类,ConcreteAllyControlCenter充当具体目标类,Observer充当抽象观察者,Player充当具体观察者。

2.代码实现
import java.util.*;
 
//抽象观察类
interface Observer {
	public String getName();
	public void setName(String name);
	public void help(); //声明支援盟友方法
	public void beAttacked(AllyControlCenter acc); //声明遭受攻击方法
}
 
//战队成员类:具体观察者类
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 + "来救你!");
	}
	
  //遭受攻击方法的实现,当遭受攻击时将调用战队控制中心类的通知方法notifyObserver()来通知盟友
	public void beAttacked(AllyControlCenter acc) {
        System.out.println(this.name + "被攻击!");
        acc.notifyObserver(name);		
	}
}
 
//战队控制中心类:目标类
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);
}
 
//具体战队控制中心类:具体目标类
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();
      }
    }		
	}
}

客户端类

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);
	}
}
相关推荐
雷神乐乐8 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|12 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
逊嘘31 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
金池尽干34 分钟前
设计模式之——观察者模式
观察者模式·设计模式
morris13139 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
也无晴也无风雨1 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU1 小时前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie61 小时前
在IDEA中使用Git
java·git