基于大话设计模式使用js和ts复写
解释
主题(subject) 和 观察者(observer),一个Subject可以拥有任意数目依赖它的Observer,一旦它的状态发生改变,所有的Observer都能收到通知。
Subject发通知并不需要谁是观察者,任何一个观察者也不需要其他观察者存在
当订阅者的更新方法不一样时,需要使用委托,原文是使用的c#,此处使用的js,由于没有委托,因此尝试使用函数实现
观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
JS
主题和观察者 抽象类
// 主题类
class Subject{
Attach(observer){} // 添加观察者
Detach(observer){} // 删除观察者
Notify(){} // 通知方法
getSecretaryAction(){} // 获取自定义文本
setSecretaryAction(action){} // 写入自定义文本
}
// 主题-具体
class Boss extends Subject {
action = ''
observers = []
Attach(observer){
this.observers.push(observer)
}
Detach(observer){
let index = this.observers.indexOf(observer)
this.observers.splice(index,1)
}
Notify(){
this.observers.forEach(item => item.Update())
}
getSecretaryAction(){
return this.action
}
setSecretaryAction(action){
this.action = action
}
}
// 观察者类
class Observer {
constructor(name,sub){
this.name = name
this.sub = sub
}
Update(){}
}
// 看股票的同事
class StockObserver extends Observer {
Update(){
console.log(`${this.name} ${this.sub.getSecretaryAction()} 关闭股票行情继续工作`)
}
}
// 看NBA的同事
class NbaObserver extends Observer {
Update(){
console.log(`${this.name} ${this.sub.getSecretaryAction()} 关闭NBA继续工作`)
}
}
function main (){
let secreatry = new Boss()
let a = new StockObserver('滕笑然',secreatry)
let b = new NbaObserver('胡汉三',secreatry)
secreatry.Attach(a)
secreatry.Attach(b)
secreatry.setSecretaryAction('老板回来了!!!!')
secreatry.Notify()
}
main()
委托类型
之所以使用委托类型,再使用三方组件的时候,可能提供了观察者的更新方法,但是这个方法名称我们不可能去改,各种各样的三方组件可能有不同的名称,此时我们要使用委托类型来解决这种方法,从外部能够自定义调用的更新方法
原文中的委托是使用c#实现的,没有找到合适的方法,暂时使用数组遍历调用,若有其他专业方法再更新
注意:由于js的this指向问题,函数指向运行时的调用者,所以此处要使用bind或者回调函数来保持this的指向,此处两种都做了演示
// 观察者模式
// 抽象-通知者
class Subject{
Notify(){} // 通知方法
getSecretaryAction(){} // 获取自定义文本
setSecretaryAction(action){} // 写入自定义文本
}
// 具体-通知者
class Boss extends Subject {
action = '' // 自定义文本
Notify(arr){
arr.forEach(item => item())
}
getSecretaryAction(){
return this.action
}
setSecretaryAction(action){
this.action = action
}
}
// 具体-观察者 看股票的同事
class StockObserver{
constructor(name,sub){
this.name = name
this.sub = sub
}
StockUpdate(){
console.log(`${this.name} ${this.sub.getSecretaryAction()} 关闭股票行情继续工作`)
}
}
// 具体-观察者 看NBA的同事
class NbaObserver {
constructor(name,sub){
this.name = name
this.sub = sub
}
NbaUpdate(){
console.log(`${this.name} ${this.sub.getSecretaryAction()} 关闭NBA继续工作`)
}
}
function main (){
let secreatry = new Boss()
let a = new StockObserver('tengyao',secreatry)
let b = new NbaObserver('zhangning',secreatry)
secreatry.setSecretaryAction('老板回来了!!!!')
secreatry.Notify([a.StockUpdate.bind(a),()=>b.NbaUpdate()]) // 此处使用回调函数和react一样,让后面的函数指向了a
}
main()
TS
主题和观察者 抽象类
// 抽象 主题
abstract class Subject2 {
public abstract Attach(observer:Observer2):void // 抽象 添加观察者方法
public abstract Detach(observer:Observer2):void // 抽象 删除观察者方法
public abstract get SecretaryAction():string; // 获取自定义文本
public abstract set SecretaryAction(action:string); // 删除自定义文本
public abstract Notify(); // 通知方法
}
// 抽象 观察者
abstract class Observer2 {
protected name:string ; // 观察者名称
protected sub:Subject2; // 主题
constructor(name:string,sub:Subject2){
this.name = name
this.sub = sub
}
public abstract Update():void;
}
class Secretary2 extends Subject2 {
private observers:StockObserver2[] = []
private action:string ;
public Attach(observer:StockObserver2):void{
this.observers.push(observer)
}
public Detach(observer:StockObserver2):void{
let index:number = this.observers.indexOf(observer)
this.observers.splice(index,1)
}
public Notify():void{
this.observers.forEach((item:StockObserver2) => item.Update())
}
public get SecretaryAction():string{
return this.action
}
public set SecretaryAction(action:string){
this.action = action
}
}
class StockObserver2 extends Observer2 {
constructor(name:string,sub:Subject2){
super(name,sub) //使用super用于继承父类方法
}
public Update():void{
console.log(`${this.name} ${this.sub.SecretaryAction} 关闭股票行情继续工作`)
}
}
class NBAObserver2 extends Observer2 {
constructor(name:string,sub:Subject2){
super(name,sub)
}
public Update():void{
console.log(`${this.name} ${this.sub.SecretaryAction} 关闭NBA继续工作`)
}
}
function main1 ():void{
let secreatry2:Secretary2 = new Secretary2()
let a:StockObserver2 = new StockObserver2('王腾瑶',secreatry2)
let b:StockObserver2 = new NBAObserver2('张宁',secreatry2)
secreatry2.Attach(a)
secreatry2.Attach(b)
secreatry2.SecretaryAction = '老板回来了!!!!'
secreatry2.Notify()
}
main1()
委托类型
ts目前百度没有找到委托类型,暂时使用一个变量存储函数,具体实现和js原理一致
abstract class Subject3 {
public abstract get SecretaryAction():string; // 抽象 获取自定义文本
public abstract set SecretaryAction(action:string); // 写入 获取自定义文本
public abstract Notify(); // 通知方法
}
type CalculationDelegate = () => void;//自定义类型
class Secretary3 extends Subject3 {
private action:string ;
private UpdateArr:CalculationDelegate[] = []; //存储 观察者更新函数 的数组
// 通知观察者方法
public Notify():void{
this.UpdateArr.forEach((fn:CalculationDelegate) => fn())
}
// 用于添加 观察者更新函数
public Update(fn:CalculationDelegate){
this.UpdateArr.push(fn)
}
public get SecretaryAction():string{
return this.action
}
public set SecretaryAction(action:string){
this.action = action
}
}
class StockObserver3 {
private name:string ;
private sub:Secretary3;
constructor(name:string,sub:Secretary3){
this.name = name
this.sub = sub
}
public stockUpdate():void{
console.log(`${this.name} ${this.sub.SecretaryAction} 关闭股票行情继续工作`)
}
}
class NBAObserver3 {
private name:string ;
private sub:Secretary3;
constructor(name:string,sub:Secretary3){
this.name = name
this.sub = sub
}
public nbaUpdate():void{
console.log(`${this.name} ${this.sub.SecretaryAction} 关闭NBA继续工作`)
}
}
function main1 ():void{
let secretary3:Secretary3 = new Secretary3()
let a:StockObserver3 = new StockObserver3('王腾瑶',secretary3)
let b:NBAObserver3 = new NBAObserver3('张宁',secretary3)
secretary3.Update(a.stockUpdate.bind(a)) // 添加a的观察方法
secretary3.Update(b.nbaUpdate.bind(b)) // 添加b的观察方法
secretary3.SecretaryAction = '老板回来了!!!!'
secretary3.Notify()
}
main1()