设计模式之观察者模式(typescript,dart,golan

2021-07-10  本文已影响0人  mudssky

现实例子

也叫做发布订阅模式,这里给出的例子是,求职者订阅了招聘网站的服务,如果有匹配的工作信息,招聘网站会进行推送

说人话

建立对象间的依赖关系,使得一个对象的状态发生改变时,所有依赖它的对象都能被通知到。

维基百科的描述

观察者模式是一种软件设计模式,在这种模式中,一个称为主体的对象维护一个称为观察者的依赖项列表,并在任何状态更改时自动通知它们(通常通过调用它们的一个方法)。

typescript example

interface Subject {
  registerObserver(o: Observer): void
  removeObserver(o: Observer): void
  notifyObservers(info: any): void
}

interface Observer {
  update(s: Subject, arg: Object): void
}

class JobInfo {
  protected info: string
  constructor(info: string) {
    this.info = info
  }
  getInfo() {
    return this.info
  }
}

class JobSite implements Subject {
  protected observers: Array<Observer>
  constructor() {
    this.observers = Array<Observer>()
  }
  registerObserver(o: Observer): void {
    this.observers.push(o)
  }
  removeObserver(o: Observer): void {
    const index = this.observers.indexOf(o)
    this.observers.splice(index, 1)
  }
  notifyObservers(info: JobInfo): void {
    for (const o of this.observers) {
      o.update(this, info)
    }
  }

  AddJob(info: JobInfo) {
    console.log('招聘网站有新的工作追加了')

    this.notifyObservers(info)
  }
}

class Jiucai implements Observer {
  name: string
  constructor(name: string) {
    this.name = name
  }
  update(s: Subject, arg: JobInfo): void {
    console.log(`${this.name}收到新工作推送,职位是${arg.getInfo()}`)
  }
}

const zibenjia = new JobSite()

const jiucai1 = new Jiucai('生命1号')
const jiucai2 = new Jiucai('脑白金')

zibenjia.registerObserver(jiucai1)
zibenjia.registerObserver(jiucai2)

zibenjia.AddJob(new JobInfo('web前端'))
zibenjia.AddJob(new JobInfo('算法工程师'))

下面是head first设计模式这本书里面关于气象站和告示板的typescript代码实现

interface Subject {
  registerObserver(o: Observer): void
  removeObserver(o: Observer): void
  notifyObservers(): void
}

interface Observer {
  update(temp: number, humidity: number, pressure: number): void
}

interface DisplayElement {
  display(): void
}

class WeatherData implements Subject {
  private observers: Array<Observer>
  private temperature!: number
  private humidity!: number
  private pressure!: number
  constructor() {
    this.observers = Array<Observer>()
  }
  registerObserver(o: Observer): void {
    this.observers.push(o)
  }
  removeObserver(o: Observer): void {
    const index = this.observers.indexOf(o)
    this.observers.splice(index, 1)
  }
  notifyObservers(): void {
    for (const o of this.observers) {
      o.update(this.temperature, this.humidity, this.pressure)
    }
  }

  measurementsChanged() {
    this.notifyObservers()
  }
  setMeasurements(temperature: number, humidity: number, pressure: number) {
    this.temperature = temperature
    this.humidity = humidity
    this.pressure = pressure
    this.measurementsChanged()
  }
}

class CurrentConditionDisplay implements Observer, DisplayElement {
  private temperature!: number
  private humidity!: number
  private weatherData: Subject
  constructor(weatherData: Subject) {
    this.weatherData = weatherData
    this.weatherData.registerObserver(this)
  }
  update(temp: number, humidity: number, pressure: number): void {
    this.temperature = temp
    this.humidity = humidity
    this.display()
  }

  display(): void {
    console.log(
      `Current conditionsc: ${this.temperature} F degrees and ${this.humidity}% humidity`
    )
  }
}

class StatisticsConditionDisplay implements Observer, DisplayElement {
  private pressure!: number
  private weatherData: Subject
  constructor(weatherData: Subject) {
    this.weatherData = weatherData
    this.weatherData.registerObserver(this)
  }
  update(temp: number, humidity: number, pressure: number): void {
    this.pressure = pressure
    this.display()
  }

  display(): void {
    console.log(`Statistics conditionsc: ${this.pressure} pressure`)
  }
}
const wd = new WeatherData()
const ccd = new CurrentConditionDisplay(wd)
const scd = new StatisticsConditionDisplay(wd)
wd.setMeasurements(80, 65, 30.4)
wd.setMeasurements(82, 75, 28.3)
wd.setMeasurements(78, 90, 36.4)

export {}

dart example

dart中Object不想typescript一样可以接受任何其他类。

所以我这里对observer 用了泛型。

abstract class Observer<T> {
  void update(Subject s, T o);
}

abstract class Subject {
  void registerObserver(Observer o);
  void removeObserver(Observer o);
  void notifyObservers(Object o);
}

class JobInfo {
  late String info;
  JobInfo(this.info);
}

class JobSite implements Subject {
  final List<Observer> observers = [];

  @override
  void registerObserver(Observer o) {
    this.observers.add(o);
  }

  @override
  void removeObserver(Observer o) {
    this.observers.remove(o);
  }

  @override
  void notifyObservers(Object o) {
    for (var item in this.observers) {
      item.update(this, o);
    }
  }

  void addJobInfo(JobInfo j) {
    print('有新的工作信息');
    this.notifyObservers(j);
  }
}

class Jiucai implements Observer<JobInfo> {
  final String name;

  Jiucai(this.name);
  @override
  void update(Subject s, JobInfo o) {
    print("$name收到新的工作推送,职位是${o.info}");
  }
}

main(List<String> args) {
  var zibenjia = JobSite();

  var jiucai1 = Jiucai('李白');
  var jiucai2 = Jiucai('白居易');

  zibenjia.registerObserver(jiucai1);
  zibenjia.registerObserver(jiucai2);
  zibenjia.addJobInfo(JobInfo('AI工程师'));
}

golang example

package main

import "fmt"

type Subject interface {
    registerObserver(o Observer)
    removeObserver(o Observer)
    notifyObservers(s Subject, o interface{})
}

type Observer interface {
    update(s Subject, o interface{})
}

type JobSite struct {
    observers []Observer
}

func (j *JobSite) registerObserver(o Observer) {
    j.observers = append(j.observers, o)
}

func (j *JobSite) removeObserver(o Observer) {
    for i := 0; i < len(j.observers); i++ {
        if o == j.observers[i] {
            j.observers = append(j.observers[:i], j.observers[i+1:]...)
            return
        }
    }
}
func (j *JobSite) notifyObservers(s Subject, o interface{}) {
    for i := 0; i < len(j.observers); i++ {
        j.observers[i].update(s, o)
    }
}
func (j *JobSite) addJobInfo(info string) {
    fmt.Println("新工作信息入库")
    j.notifyObservers(j, info)
}

type Jiucai struct {
    name string
}

func (j *Jiucai) update(s Subject, o interface{}) {
    fmt.Printf("%s收到新的工作推送,职位是%v\n", j.name, o)
}
func main() {
    zibenjia := JobSite{observers: []Observer{}}
    jiucai1 := Jiucai{name: "张三"}
    jiucai2 := Jiucai{name: "李四"}
    zibenjia.registerObserver(&jiucai1)
    zibenjia.registerObserver(&jiucai2)
    zibenjia.addJobInfo("喝牛奶")

}

上一篇下一篇

猜你喜欢

热点阅读