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) 访问者
参与者:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 这样以后就可将该对象恢复到原先保存的状态。
有时有必要记录一个对象的内部状态。为了允许用户取消不确定的操作或从错误中恢复过来,需要实现检查点和取消机制 , 而要实现这些机制,你必须事先将状态信息保存在某处, 这样才能将对象恢复到它们先前的状态。但是对象通常封装了其部分或所有的状态信息 , 使得其状态不能被其他对象访问,也就不可能在该对象之外保存其状态。而暴露其内部状态又将违反封装的原则,可能有损应用的可靠性和可扩展性。
例如,考虑一个图形编辑器,它支持图形对象间的连线。用户可用一条直线连接两个矩 形, 而当用户移动任意一个矩形时 ,这两个矩形仍能保持连接。在移动过程中,编辑器自动伸展这条直线以保持该连接。
一个众所周知的保持对象间连接关系的方法是使用一个约束解释系统。我们可将这一功能封装在一个ConstraintSolver对象中。ConstraintSolver在连接生成时,记录这些连接并产生
描述它们的数学方程。当用户生成一个连接或修改图形时,ConstraintSolver就求解这些方程。并根据它的计算结果重新调整图形,使各个对象保持正确的连接。
一个备忘录(memento)是一个对象,它存储另一个对象在某个瞬间的内部状态,而后者称为备忘录的原发器(originator)。当需要设置原发器的检查点时,取消操作机制会向原发器请求一个备忘录。原发器用描述当前状态的信息初始化该备忘录。只有原发器可以向备忘录中存取信息,备忘录对其他的对象“不可见”。
在刚才讨论的图形编辑器的例子中,ConstraintSolver可作为一个原发器。下面的事件序列描述了取消操作的过程:
1)作为移动操作的一个副作用,编辑器向ConstraintSolver请求一个备忘录。
2)ConstraintSolver创建并返回一个备忘录,在这个例子中该备忘录是SolverState类的一个实例。SolverState备忘录包含一些描述ConstraintSolver的内部等式和变量当前状态的数据结构。
3)此后当用户取消移动操作时,编辑器将SolverState备忘录送回给ConstraintSolver。
4)根据SolverState备忘录中的信息,ConstraintSolver改变它的内部结构以精确地将它的等式和变量返回到它们各自先前的状态。
这一方案允许ConstraintSolver把恢复先前状态所需的信息交给其他的对象,而又不暴露它的内部结构和表示。
export default class ConstraintSolverMemento {
state;
constructor() {
}
Setstate(state)
{
this.state=state;
}
Getstate()
{
return this.state;
}
}
export default class ConstraintSolver {
static #instance;//静态私有变量
ItemChildrens=[];
constructor() {
if(!ConstraintSolver.#instance){
ConstraintSolver.#instance = this
}
return ConstraintSolver.#instance
}
static Instance() {
if (!this.#instance) this.#instance = new ConstraintSolver();
return this.#instance;
}
Solve()
{
for(let n=0;n=0 && line2dir>=0)
return 1;
else if(line1dir>=0 && line2dir<0)
return 2;
else if(line1dir<0 && line2dir>=0)
return 3;
else
return 4;
}
AddConstraint(startGraphic,endGraplethic){
let link={start:startGraphic,end:endGraplethic,link:{}};
this.ItemChildrens.push(link);
}
RemoveConstraint(startGraphic,endGraphic){
}
CreateMemento()//重点
{
return this.ItemChildrens;
}
SetMemento(memento)//重点
{
this.ItemChildrens=memento;
}
Draw(ctx)
{
for(let n=0;n
import MoveCommand from './Command/impl/MoveCommand.js';
export default class UnDoRedo {
#_Undocommands = [];
#_Redocommands = [];
constructor() {
}
GetUndoLength() {
return this.#_Undocommands.length;
}
GetRedoLength() {
return this.#_Redocommands.length;
}
Redo() {
if (this.#_Redocommands.length != 0) {
let command = this.#_Redocommands.pop();
command.Execute();
this.#_Undocommands.push(command);
}
}
Undo() {
if (this.#_Undocommands.length != 0) {
let command = this.#_Undocommands.pop();
command.UnExecute();
this.#_Redocommands.push(command);
}
}
InsertInUnDoRedoForMove(target, point) {
let cmd = new MoveCommand(target, point);
cmd.Execute();
this.#_Undocommands.push(cmd);
this.#_Redocommands = [];
}
}
import Rectangle from './Widget/impl/Rectangle.js';
import Button from './Widget/impl/Button.js';
import ConstraintSolver from './Solver/ConstraintSolver.js';
import UnDoRedo from './UnDoRedo.js';
export default class Application{
ctx;
zooRect;
ItemChildrens=[];
unDoRedo;
// ItemZooChildrens=[];
solver= ConstraintSolver.Instance();
constructor(ctx,zooRect) {
this.ctx=ctx;
this.unDoRedo=new UnDoRedo();
this.zooRect=zooRect;
this.createElement(ctx);
this.Draw();
}
Draw()
{
this.ctx.clearRect(this.zooRect.startx,this.zooRect.starty,this.zooRect.width,this.zooRect.height);
for(let n=0;n{ //撤销
let undoLenth= this.unDoRedo.GetUndoLength();
if(undoLenth>0)
{
this.unDoRedo.Undo();
this.Draw();
}
}
});
button2.AddClickEvent(
{
ClickEvent:(button,e) =>{ //重做
let undoLenth= this.unDoRedo.GetRedoLength();
if(undoLenth>0)
{
this.unDoRedo.Redo();
this.Draw();
}
}
});
let rect1Pos={startx:250,starty:50,width:100,height:50};
let rect2Pos={startx:250,starty:150,width:100,height:50};
let rect1=new Rectangle(ctx,'rect1',rect1Pos);
rect1.AddDragEvent(this);
rect1.AddDragOverEvent(this);
let rect2=new Rectangle(ctx,'rect2',rect2Pos);
this.ItemChildrens.push(rect1);
this.ItemChildrens.push(rect2);
this.ItemChildrens.push(button1);
this.ItemChildrens.push(button2);
this.solver.AddConstraint(rect1,rect2);
this.solver.Solve();
}
DragEvent(target,e)
{
var x = e.clientX;
var y = e.clientY;
this.Draw();
}
DragOverEvent(target,e)
{
var x = e.clientX;
var y = e.clientY;
this.unDoRedo.InsertInUnDoRedoForMove(target,{x:e.clientX,y:e.clientY});
console.log(`DragOver 移动 x:`+x +'y:'+y);
}
}
测试结果:
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut