typescript: Observer Pattern
/**
* Observer Pattern 观察者是一种行为设计模式, 允许一个对象将其状态的改变通知其他对象
* file: Observerts.ts
* The Subject interface declares a set of methods for managing subscribers.
*/
interface GeovinSubject {
// Attach an observer to the subject.
attach(observer: Observer):string ; //void
// Detach an observer from the subject.
detach(observer: Observer):string ; //void
// Notify all observers about an event.
notify(): string; //void
}
/**
* The Subject owns some important state and notifies observers when the state
* changes.
*/
class ConcreteSubject implements GeovinSubject {
/**
* @type {number} For the sake of simplicity, the Subject's state, essential
* to all subscribers, is stored in this variable.
*/
public state: number;
/**
* @type {Observer[]} List of subscribers. In real life, the list of
* subscribers can be stored more comprehensively (categorized by event
* type, etc.).
*/
private observers: Observer[] = [];
/**
* The subscription management methods.
*/
public attach(observer: Observer): string { //void
const isExist = this.observers.includes(observer); //es2016 later
if (isExist) {
// console.log('Subject: Observer has been attached already.');
return "Subject: Observer has been attached already.";
}
console.log('Subject: Attached an observer.');
this.observers.push(observer);
return "Subject: Attached an observer.";
}
public detach(observer: Observer): string {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex === -1) {
console.log('Subject: Nonexistent observer.');
return "Subject: Nonexistent observer.";
}
this.observers.splice(observerIndex, 1);
console.log('Subject: Detached an observer.');
return "Subject: Detached an observer.";
}
/**
* Trigger an update in each subscriber.
*/
public notify(): string {
let getstr="";
console.log('Subject: Notifying observers...');
for (const observer of this.observers) {
observer.update(this);
getstr=getstr+"Subject: Notifying observers...";
}
return getstr;
}
/**
* Usually, the subscription logic is only a fraction of what a Subject can
* really do. Subjects commonly hold some important business logic, that
* triggers a notification method whenever something important is about to
* happen (or after it).
*/
public someBusinessLogic(): string { //void
let getstr="";
console.log('\nSubject: I\'m doing something important.');
this.state = Math.floor(Math.random() * (10 + 1));
getstr=getstr+this.state.toString();
console.log(`Subject: My state has just changed to: ${this.state}`);
getstr=getstr+this.notify();
return getstr;
}
}
/**
* 接口
* The Observer interface declares the update method, used by subjects.
*/
interface Observer {
// Receive update from subject.
update(subject: GeovinSubject): string; //void
}
/**
* Concrete Observers react to the updates issued by the Subject they had been
* attached to.
*/
class ConcreteObserverA implements Observer {
/**
*
* @param subject
* @returns
*/
public update(subject: GeovinSubject): string { //void
if (subject instanceof ConcreteSubject && subject.state < 3) {
console.log('ConcreteObserverA: Reacted to the event.');
return "ConcreteObserverA: Reacted to the event.";
}
}
}
/**
*
*/
class ConcreteObserverB implements Observer {
/**
*
* @param subject
* @returns
*/
public update(subject: GeovinSubject): string { //void
if (subject instanceof ConcreteSubject && (subject.state === 0 || subject.state >= 2)) {
console.log('ConcreteObserverB: Reacted to the event.');
return "ConcreteObserverB: Reacted to the event.";
}
}
}
//bing AI 生成的代码示例
// 定义被观察者接口
interface Observable {
// 添加观察者
addObserver(observer: DuObserver): void;
// 删除观察者
removeObserver(observer: DuObserver): void;
// 通知所有观察者
notifyObservers(): void;
}
// 定义观察者接口
interface DuObserver {
// 接收被观察者的通知
update(observable: Observable): void;
}
// 定义一个具体的被观察者类:温度计
class Thermometer implements Observable {
// 存储观察者列表
private observers: DuObserver[] = [];
// 存储温度值
private temperature: number;
// 添加观察者
public addObserver(observer: DuObserver): void {
this.observers.push(observer);
console.log("添加了一个观察者");
}
// 删除观察者
public removeObserver(observer: DuObserver): void {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
console.log("删除了一个观察者");
}
}
// 通知所有观察者
public notifyObservers(): void {
for (const observer of this.observers) {
observer.update(this);
}
console.log("通知了所有观察者");
}
// 获取温度值
public getTemperature(): number {
return this.temperature;
}
// 设置温度值,并通知所有观察者
public setTemperature(temperature: number): void {
this.temperature = temperature;
console.log("温度变化了");
this.notifyObservers();
}
}
// 定义一个具体的观察者类:手机
class Phone implements DuObserver {
// 接收被观察者的通知,并打印温度值
public update(observable: Observable): void {
if (observable instanceof Thermometer) {
console.log("手机收到了温度变化的通知,温度是:" + observable.getTemperature());
}
}
}
// 定义一个具体的观察者类:电脑
class Computer implements DuObserver {
// 接收被观察者的通知,并打印温度值
public update(observable: Observable): void {
if (observable instanceof Thermometer) {
console.log("电脑收到了温度变化的通知,温度是:" + observable.getTemperature());
}
}
}
// 测试代码
const thermometer = new Thermometer(); // 创建一个温度计对象
const phone = new Phone(); // 创建一个手机对象
const computer = new Computer(); // 创建一个电脑对象
thermometer.addObserver(phone); // 让手机订阅温度计
thermometer.addObserver(computer); // 让电脑订阅温度计
thermometer.setTemperature(25); // 设置温度为25
thermometer.removeObserver(phone); // 让手机取消订阅
thermometer.setTemperature(30); // 设置温度为30
//ECMAScript 2023
//https://262.ecma-international.org/14.0/
//https://github.com/tc39/ecma262
let pubObserver1="";
let pubObserver2="";
let pubObserver3="Geovin Du";
let pubObserver4="geovindu";
/**
* The client code.
*/
const subject = new ConcreteSubject();
const observer1 = new ConcreteObserverA();
pubObserver1=subject.attach(observer1);
const observer2 = new ConcreteObserverB();
subject.attach(observer2);
pubObserver2=subject.someBusinessLogic();
pubObserver3=subject.someBusinessLogic();
subject.detach(observer2);
pubObserver4=subject.someBusinessLogic();
let messageObserver: string = 'Hello World,This is a typescript!,涂聚文 Geovin Du.Web';
document.body.innerHTML = messageObserver+",<br/>one="+pubObserver1+",<br/>two="+pubObserver2+",<br/>three="+pubObserver3+",<br/>four="+pubObserver4+",<br/>TypeScript Observer Pattern 观察者模式";
调用:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<head><title>TypeScript Hello Observer Pattern 观察者模式</title>
<meta name="Description" content="geovindu,涂聚文,Geovin Du"/>
<meta name="Keywords" content="geovindu,涂聚文,Geovin Du"/>
<meta name="author" content="geovindu,涂聚文,Geovin Du"/>
</head>
<body>
<script src="dist/Observerts.js"></script>
</body>
</html>
输出:

哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号