观察者设计模式:又被称作是发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个对象的状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。
解决的问题:将系统分割成一些类或者相互协作的类,会有一个不好的副作用。那就是需要维护相关对象的一致性。我们不希望为了维护一致性而使得各种类紧密耦合,这样会给维护扩展重用都带来不便。观察者就是解决这一类问题的。
典型的观察者设计模式(双向耦合)
Secretary.java-通知类
public class Secretary {
//同事列表
private List<StockObserver> observers=new ArrayList<StockObserver>();
private String action;
//增加
public void attach(StockObserver observer){
observers.add(observer);
}
public void inform(){
for(StockObserver s:observers){
s.update();
}
}
//前台状态
public String SecretaryAction;
public String getSecretaryAction() {
return SecretaryAction;
}
public void setSecretaryAction(String secretaryAction) {
SecretaryAction = secretaryAction;
}
}
StockObserver.java-订阅类
public class StockObserver {
private String name;
private Secretary sub;
public StockObserver(String name,Secretary sub){
this.name=name;
this.sub=sub;
}
public void update() {
System.out.println(sub.SecretaryAction+" "+name+" 关闭股票行情,继续努力工作");
}
}
测试
public class Test {
public static void main(String[] args) {
//前台
Secretary secretary = new Secretary();
//看股票的同事
StockObserver stockObserver1 = new StockObserver("张三",secretary);
StockObserver stockObserver2 = new StockObserver("李四",secretary);
//前台记录下两位同事
secretary.attach(stockObserver1);
secretary.attach(stockObserver2);
secretary.setSecretaryAction("Boss回来了!!!");
secretary.inform();
}
}
输出
典型的观察者设计模式(抽象观察者和订阅者)
Subject.java-抽象通知类
public abstract class Subject {
abstract void attach(Observer observer);
abstract void detach(Observer observer);
abstract void inform();
protected String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
Boss.java-具体通知类
public class Boss extends Subject{
//同事列表
//private 只有当前类可以访问
private List<Observer> observers=new ArrayList<Observer>();
private String action;
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void inform() {
for(Observer o:observers){
o.update();
}
}
}
Observer.java-抽象订阅者
public abstract class Observer {
//protected 同一个包中可以访问,继承的子类可以访问
protected String name;
protected Subject sub;
public abstract void update();
public Observer(String name,Subject sub){
this.name=name;
this.sub=sub;
}
}
NBAObserver.java-具体订阅者
public class NBAObserver extends Observer{
public NBAObserver(String name, Subject sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getSubjectState()+" "+name+" 关闭NBA直播继续工作!!!");
}
}
StockObserver.java-具体订阅者
public class StockObserver extends Observer{
public StockObserver(String name, Subject sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getSubjectState()+" "+name+" 关闭股票行情继续工作!!!");
}
}
测试
public class Test {
public static void main(String[] args) {
Subject boss = new Boss();
Observer observer1 = new NBAObserver("张三",boss);
Observer observer2 = new StockObserver("李四",boss);
boss.attach(observer1);
boss.attach(observer2);
boss.setSubjectState("我胡汉三回来了!");
boss.inform();
}
}
输出
观察者设计模式:观察者设计模式解决的问题时当一个对象发生指定的动作时,要通过另外一个对象做出相应的处理。
需求: 编写一个气象站、一个工人两个类,当气象站更新天气 的时候,要通知人做出相应的处理。
问题1: 气象站更新了多次天气,然后人才做一次的处理。
问题2: 目前气象站只能通知一个人而已。
问题3: 在现实生活中出了工人群体要关注天气,其他 的群体也需要关注天气
观察者设计模式的步骤:
1. 当前目前对象发生指定的动作是,要通知另外一个对象做出相应的处理,这时候应该把对方的相应处理方法定义在接口上。
2. 在当前对象维护接口的引用,当当前对象发生指定的动作这时候即可调用接口中的方法了。
//人 是要根据天气做出相应的处理的。
public class Emp implements Weather{
String name;
public Emp(String name) {
this.name = name;
}
//人是要根据天气做出相应的处理的。 "晴天","雾霾","刮风","冰雹","下雪"
public void notifyWeather(String weather){
if("晴天".equals(weather)){
System.out.println(name+"高高兴兴的去上班!!");
}else if("雾霾".equals(weather)){
System.out.println(name+"戴着消毒面具去上班!");
}else if("刮风".equals(weather)){
System.out.println(name+"拖着大石头过来上班!");
}else if("冰雹".equals(weather)){
System.out.println(name+"戴着头盔过来上班!");
}else if("下雪".equals(weather)){
System.out.println(name+"戴着被子过来上班!");
}
}
}
public class Student implements Weather{
String name;
public Student(String name) {
super();
this.name = name;
}
public void notifyWeather(String weather){
if("晴天".equals(weather)){
System.out.println(name+"高高兴兴的去开学!!");
}else if("雾霾".equals(weather)){
System.out.println(name+"吸多两口去上学!");
}else if("刮风".equals(weather)){
System.out.println(name+"在家睡觉!");
}else if("冰雹".equals(weather)){
System.out.println(name+"在家睡觉!");
}else if("下雪".equals(weather)){
System.out.println(name+"等下完再去上学!");
}
}
}
//订阅天气预报的接口
public interface Weather {
public void notifyWeather(String weather);
}
//气象站
public class WeatherStation {
String[] weathers = {"晴天","雾霾","刮风","冰雹","下雪"};
//当前天气
String weather ;
//该集合中存储的都是需要收听天气预报的人
ArrayList<Weather> list = new ArrayList<Weather>(); //程序设计讲究低耦合---->尽量不要让一个类过分依赖于另外一个类。
public void addListener(Weather e){
list.add(e);
}
//开始工作
public void startWork() {
final Random random = new Random();
new Thread(){
@Override
public void run() {
while(true){
updateWeather(); // 每1~1.5秒更新一次天气 1000~1500
for(Weather e : list){
e.notifyWeather(weather);
}
int s = random.nextInt(501)+1000; // 500
try {
Thread.sleep(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
//更新天气的 方法
public void updateWeather(){
Random random = new Random();
int index = random.nextInt(weathers.length);
weather = weathers[index];
System.out.println("当前的天气是: " + weather);
}
}
public class WeatherMain {
public static void main(String[] args) throws Exception {
//工人
Emp e = new Emp("小明");
Emp e2 = new Emp("如花");
//学生
Student s1 = new Student("狗娃");
Student s2 = new Student("狗剩");
WeatherStation station = new WeatherStation();
station.addListener(e);
station.addListener(e2);
station.addListener(s1);
station.addListener(s2);
station.startWork();
}
}
观察者模式多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。