观察者模式的定义?
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为
那什么是观察者模式?
举一个例子:
1.淘宝快递
2.一旦你购买了商品,就会快递到你家里,你要你一直购买商品,你就一直会收到新的快递。
3.你不再购买商品,就不会收到快递了
4 淘宝在运营的时候,一直会有人去购买或者退货。
在观察者模式里面:淘宝(Subject), 购买者(Observers)
当多个对象订阅一个物体时,订阅物体发生变化时,那些订阅了的对象就会有相应的变化就是观察者模式
发布者 + 订阅者 = 观察者模式
为什么使用观察者模式?
观察者模式是松耦合。
怎么判断是松耦合
- 松耦合的时候, 他们可以进行交互, 但是却几乎不了解对方.
- 被观察者(Subject)只知道观察者实现了某个接口
- 可以随时添加观察者
- 添加新类型观察者的时候不需要修改被观察者
- 可以复用观察者或者被观察者
- 如果被观察者或观察者发生变化了, 那么这些变化不会影响到对方.
观察者模式的结构
- 抽象主题角色:抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
- 抽象观察者角色:为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
- 具体主题角色:实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
- 具体观察者角色:实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。
当更换主题的状态相应的观察者会执行:
例子一:
定义抽象更新数据接口
public abstract class AbstractObserver
{
public abstract void Update();
}
定义抽象的主题
public abstract class AbstractTheme
{
//主题的状态
private string AbstractThemeState;
public List<AbstractObserver> observers = new List<AbstractObserver>();
public void Addobserver(AbstractObserver abstractObserver) => observers.Add(abstractObserver);
public void Removeobserver(AbstractObserver abstractObserver) => observers.Remove(abstractObserver);
public void Notify()
{
foreach (AbstractObserver o in observers)
{
o.Update();
}
}
}
具体的观察者
public class AbstractA : AbstractObserver
{
private ConcreteTheme concreteTheme;
public AbstractA(ConcreteTheme concreteTheme_ )
{
this.concreteTheme= concreteTheme_;
}
public override void Update()
{
if (concreteTheme.State == "A")
{
Debug.Log("轮到了A");
}
}
}
public class ConcreteObserver_ : AbstractObserver
{
private ConcreteTheme concreteTheme;
public ConcreteObserver_(ConcreteTheme ConcreteTheme_)
{
this.concreteTheme = ConcreteTheme_;
}
public override void Update()
{
if (concreteTheme.State == "B")
{
Debug.Log("轮到了 观察者B");
}
}
}
具体的主题
public class ConcreteTheme : AbstractTheme
{
public string State { get; set; }
}
调用
private ConcreteTheme concreteTheme;
private void Start()
{
concreteTheme = new ConcreteTheme();
concreteTheme.Addobserver(new ConcreteObserver_(concreteTheme));
concreteTheme.Addobserver(new AbstractA(concreteTheme));
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
concreteTheme.State = "A";
concreteTheme.Notify();
}
if (Input.GetKeyDown(KeyCode.B))
{
concreteTheme.State = "B";
concreteTheme.Notify();
}
}
例子二:
/*************************
* 定义观察者更新的接口
**********************/
public interface AbstractObserver
{
void InitInfo();
void UpdateInfo();
}
/****************
* 定义抽象主题
************/
using System.Collections.Generic;
public abstract class AbstractSubject
{
public List<AbstractObserver> abstracts = new List<AbstractObserver>();
public void AddAbstracts(AbstractObserver abstractObserver) => abstracts.Add(abstractObserver);
public void RemoveAbstracts(AbstractObserver abstractObserver)
{
if (abstracts.Count > 0)
{
abstracts.Remove(abstractObserver);
}
}
public void InitNotity()
{
foreach (AbstractObserver observer in abstracts)
{
observer.InitInfo();
}
}
public void UpadteNotity()
{
foreach (AbstractObserver observer in abstracts)
{
observer.UpdateInfo();
}
}
}
/****
* 具体主题
*****/
public class PhoneInfo:AbstractSubject
{
public string phoneName;
public string phoneType;
public PhoneInfo(string phoneName_,string phoneType_)
{
this.phoneName = phoneName_;
this.phoneType = phoneType_;
}
public void UpadtePhoneInfo(string phoneName_, string phoneType_)
{
this.phoneName = phoneName_;
this.phoneType = phoneType_;
}
}
/***
* 观察者A
* **/
using UnityEngine;
public class ProgrammerA : AbstractObserver
{
private string name;
private string phoneName;
private PhoneInfo phoneInfo;
public ProgrammerA(PhoneInfo phoneInfo_,string name_)
{
this.name = name_;
this.phoneInfo = phoneInfo_;
this.phoneName = phoneInfo_.phoneName;
}
public void InitInfo()
{
Debug.LogError(string.Format("程序员:{0}需要的数据是:{1}", name, phoneName));
}
public void UpdateInfo()
{
phoneName = phoneInfo.phoneName;
Debug.LogError(string.Format(" 数据更新后 程序员:{0}需要的数据是:{1}", name, phoneName));
}
}
/***
* 观察者B
* */
using UnityEngine;
public class ProgrammerB: AbstractObserver
{
private string name;
private string phoneType;
private PhoneInfo phoneInfo;
public ProgrammerB(PhoneInfo phoneInfo_,string name_)
{
this.name = name_;
this.phoneInfo = phoneInfo_;
this.phoneType = phoneInfo_.phoneType;
}
public void InitInfo()
{
Debug.LogError(string.Format("程序员:{0}需要的数据是:{1}", name, phoneType));
}
public void UpdateInfo()
{
phoneType = phoneInfo.phoneType;
Debug.LogError(string.Format(" 数据更新后 程序员:{0}需要的数据是:{1}", name, phoneType));
}
}
/***
* 调用
* */
using UnityEngine;
public class CarryOut : MonoBehaviour
{
private PhoneInfo phoneInfo;
void Start()
{
phoneInfo = new PhoneInfo("小米","Mix3");
phoneInfo.AddAbstracts(new ProgrammerA(phoneInfo,"A"));
phoneInfo.AddAbstracts(new ProgrammerB(phoneInfo, "B"));
phoneInfo.InitNotity();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
phoneInfo.UpadtePhoneInfo("iPhone", "iPhone 11 Pro");
phoneInfo.UpadteNotity();
}
}
}
网友评论