JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设原则、设计变化方向,环境相关等信息请查看设计模式开篇。
所有JAVA SCRIPT设计模式快捷连接:
创建型:(1) 抽象工厂 (2) 生成器 (3) 工厂方法 (4) 原型 (5) 单例
结构型:(6) 适配器 (7) 桥接 (8) 组合 (9) 装饰 (10) 外观 (11) 享元 (12) 代理
行为型:(13) 职责链 (14) 命令 (15) 解释器 (16) 迭代器 (17) 中介者 (18) 备忘录 (119) 观察者 (20) 状态 (21) 策略 (22) 模板方法 (23) 访问者
参与者:
定义对象间的一种一对多的依赖关系 ,当一个对象的状态发生改变时 , 所有依赖于它的对象都得到通知并被自动更新。
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一 致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。
例如, 许多图形用户界面工具箱将用户应用的界面表示与底下的应用数据分离。定义应用数据的类和负责界面表示的类可以各自独立地复用。一个表格对象和一个柱状图对象可使用不同的表示形式描述同一个应用 数据对象的信息。表格对象和柱状图对象互相并不知道对方的存在,这样使你可以根据需要 单独复用表格或柱状图。但在这里是它们表现的似乎互相知道。当用户改变表格中的信息时 , 柱状图能立即反映这一变化 , 反过来也是如此。
这一行为意味着表格对象和棒状图对象都依赖于数据对象 , 因此数据对象的任何状态改变都应立即通知它们。同时也没有理由将依赖于该数据对象的对象的数目限定为两个, 对相同的数据可以有任意数目的不同用户界面。
Observer模式描述了如何建立这种关系。这一模式中的关键对象是目标(subject)和观察者(observer)。一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的
观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。
这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者。它发出通知时并不需知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。
export default class Subject {listObservers=[];constructor( ) {}Attach(observers){this.listObservers.push(observers)}Notify(){for(let n=0;n
export default class Observer {constructor( ) {}Update(subject){console.log(`Observer 继承次类,重写此类方法,订阅者获取到消息`);}}
import Subject from './Subject.js'; export default class DataModel extends Subject {a;b;c;constructor( ) {super();}SetValue(a,b,c){this.a=a;this.b=b;this.c=c;super.Notify();}GetValue(){return {a:this.a,b:this.b,c:this.c}}}
import Observer from '../OneDataModel/Observer.js';export default class Widge extends Observer{ctx;rect;constructor(ctx,rect ) {super();this.ctx=ctx;this.rect=rect;}Draw(){}}
import Widget from '../Widget.js';
import Observer from '../../OneDataModel/Observer.js';export default class BarShow extends Widget {barValue;constructor(ctx, rect) {super(ctx, rect);}Draw() {this.ctx.clearRect(this.rect.startx, this.rect.starty, this.rect.width, this.rect.height);this.ctx.lineWidth = 1;this.ctx.strokeRect(this.rect.startx, this.rect.starty, this.rect.width, this.rect.height);let x = this.rect.startx;let y = this.rect.starty;//以下效果代码this.ctx.beginPath();this.ctx.lineWidth = "4";this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.fillRect(x + 20, y + 150, 20, -this.barValue.a);this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.fillRect(x + 60, y + 150, 20, -this.barValue.b);this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.fillRect(x + 100, y + 150, 20, -this.barValue.c);this.ctx.stroke();this.ctx.font="12px Arial";this.ctx.fillText(`BarShow a:` + this.barValue.a + `% b:` + this.barValue.b + `% c:` + this.barValue.c+ `%`,x+10,this.rect.starty+this.rect.width-30);//效果代码end}Update(subject) {this.barValue = subject.GetValue();console.log(`BarShow a:` + this.barValue.a + ` b:` + this.barValue.b + ` c:` + this.barValue.c);this.Draw();}}
import Widget from '../Widget.js';
import Observer from '../../OneDataModel/Observer.js';
export default class PieShow extends Widget {value;constructor(ctx, rect) {super(ctx, rect);}Draw() {this.ctx.clearRect(this.rect.startx, this.rect.starty, this.rect.width, this.rect.height);this.ctx.lineWidth = 1;this.ctx.strokeRect(this.rect.startx, this.rect.starty, this.rect.width, this.rect.height);let x = this.rect.startx;let y = this.rect.starty;let aPer = this.value.a / 100;let bPer = this.value.b / 100;let cPer = this.value.c / 100;//以下效果代码let start = 0;let end = aPer;//产生随机颜色this.ctx.beginPath();this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.moveTo(x + 100, y + 100);this.ctx.arc(x + 100, y + 100, 50, start * Math.PI * 2, end * Math.PI * 2)this.ctx.fill();this.ctx.stroke();start = end;end=aPer+bPer;this.ctx.beginPath();this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.moveTo(x + 100, y + 100);this.ctx.arc(x + 100, y + 100, 50, start * Math.PI * 2, end * Math.PI * 2)this.ctx.fill();this.ctx.stroke();start = end;end=aPer+bPer+cPer;this.ctx.beginPath();this.ctx.fillStyle = '#' + Math.floor(Math.random() * 0xffffff).toString(16);this.ctx.moveTo(x + 100, y + 100);this.ctx.arc(x + 100, y + 100, 50, start * Math.PI * 2, end * Math.PI * 2)this.ctx.fill();this.ctx.stroke();//效果代码endthis.ctx.font = "12px Arial";this.ctx.fillText(`PieShow a:` + this.value.a + `% b:` + this.value.b + `% c:` + this.value.c+ `%`, x + 10, this.rect.starty + this.rect.width - 30);}Update(subject) {this.value = subject.GetValue();console.log(`PieShow a:` + this.value.a + ` b:` + this.value.b + ` c:` + this.value.c);this.Draw();}
}
import DataModel from './OneDataModel/DataModel.js';
import BarShow from './Widget/impl/BarShow.js';
import PieShow from './Widget/impl/PieShow.js'; export default class Client{constructor(ctx,zooRect) {let dataModel=new DataModel();let barShow=new BarShow(ctx,{startx:50,starty:50,width:200,height:200});dataModel.Attach(barShow);let pieShow=new PieShow(ctx,{startx:350,starty:50,width:200,height:200});dataModel.Attach(pieShow);dataModel.SetValue(50,30,20);/**模拟等待三秒后,实际调用**/setInterval(() => { console.log(` 定时更新 dataModel`);let end=true;let a,b,c;do{a=Math.floor(Math.random()*(100-1)+1);b=Math.floor(Math.random()*(100-1)+1);c=100-a-b;if(c>0) end=false;}while(end)dataModel.SetValue(a,b,c);} , 3000 )}}
测试结果:
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut
下一篇:C++经典题目