本文会说一下几个阶段中的几种设计模式,分别是元素创建型:工厂模式、建造者模式和单例模式,结构型:适配器模式、装饰器模式和代理模式,行为型:命令模式、模板模式、观察者模式和职责链模式
元素创建型,顾名思义就是用来创建元素,元素创建型的设计模式目的就是规范创建方式
隐藏创建过程,暴露共同接口
exm: 在商店里下载游戏,同时初始化并运行,商店里有很多游戏,那么Game类进行游戏的各种操作,而Shop就相当于一个工厂,只负责调用去生产即可
class Shop {
constructor(name) {
return new Game(name);
}
}
class Game {
constructor(name) {
this.name = name;
}
init() {
console.log('inint');
}
run() {
console.log('run');
}
}
const dnf = new Shop('dnf');
// const dnf = new Game('dnf');
dnf.init();//inint
dnf.run();//run
// 创建商店时快速生产了游戏
通过工厂模式,可以实现工厂和工具的分离,工具只负责自己的内在功能,而工厂只需要负责生产即可
拆分简单模块、独立执行 => 注重过程与搭配
exm: 优惠套餐单元,商品 + 皮肤 进行打折售卖
class Product {
constructor(name) {
this.name = name;
}
init() {
console.log('Product init');
}
}
class Skin {
constructor(name) {
this.name = name;
}
init() {
console.log('Skin init');
}
}
class Shop {
constructor() {
this.package = '';
}
create(name) {
this.package = new PackageBuilder(name);
}
getGamePackage() {
return this.package.getPackage();
}
}
class PackageBuilder {
constructor(name) {
this.game = new Product(name);
this.skin = new Skin(name);
}
getPackage() {
return this.game.init() + this.skin.init();
}
}
const dnf = new Shop();
dnf.create('dnf');
dnf.getGamePackage();//Product init Skin init
// 每个模块独立解耦,而建造者负责创建串联整体系统
全局只有一个实例,不能乱掉,比如Vue-router就是单例模式做的
class PlayStation {
constructor() {
this.state = 'off';
}
play() {
if (this.state === 'on') {
console.log('别闹,已经在happy了');
return;
}
this.state = 'on';
console.log('开始happy');
}
shutdown() {
if (this.state === 'off') {
console.log('已经关闭');
return;
}
this.state = 'off';
console.log('已经关机,请放心');
}
// static instance = undefined;这里写在类里面,主要是为了可读性高一点,但个人感觉写在类外面更好,将类的东西定义起来,处理方法写在外面
// static getInstance() {
// return function() {
// if(!PlayStation.instance) {
// PlayStation.instance = new PlayStation();
// }
// return PlayStation.instance;
// }();
// }
}
// main.js
// PlayStation.instance = undefined;
// PlayStation.getInstance = (function() {
// return function() {
// if(!PlayStation.instance) {
// PlayStation.instance = new PlayStation();
// }
// return PlayStation.instance;
// }()
// })
const ps1 = PlayStation.getInstance();
ps1.play();//开始happy
const ps2 = PlayStation.getInstance();
ps2.shutdown();//已经关机,请放心
// 全局只要一个实例,不能乱
总结一下:
模式场景
实际应用
Button Producer:生产不同类型的按钮 => 生产多个本质相同,利用传参区分不同属性的元素 => 工厂
全局应用 router store => 只需要一个实例 => 单例
页头组件Header: 包含了title、button、breadcum => 生产多重不同类型的元素 => 建造者
功能: 优化结构的实现方式
适配独立模块,保证模块间的独立解耦且连接兼容上
exm: 买了一个港行PS,插座是国标
class HKDevice {
getPlug() {
return '港行双圆柱插头';
}
}
class Target {
constructor() {
this.plug = new HKDevice();
}
getplug() {
return this.plug.getPlug() + '港行双圆柱转换器';
}
}
const target = new Target();
console.log(target.getplug());//港行双圆柱插头港行双圆柱转换器
适配独立模块,保证模块间的独立解耦且连接兼容
exm: 设备升级
class Device {
create() {
console.log('PS4');
}
}
class Phone {
create() {
console.log('iPhone100');
}
}
class Decorator {
constructor(device) {
this.device = device;
}
create() {
this.device.create();
this.update(device);
}
update(device) {
console.log(device + 'Pro');
}
}
const device = new Device();
device.create();//PS4
const devicePro = new Decorator(device);
devicePro.create();//PS4 [object Object]Pro
使用代理人来替代原始对象
**exm:**游戏防沉迷
class Game {
play() {
console.log('playing');
}
}
class Player {
constructor(age) {
this.age = age;
}
}
class GameProxy {
constructor(player) {
this.player = player;
}
play() {
return (this.player.age < 16) ? "too young to play" : new Game().play();
}
}
const youngPlayer = new Player(15);
const youngGame = new GameProxy(youngPlayer);
console.log(youngGame.play());//too young to play
const player = new Player(18);
const game = new GameProxy(player);
game.play();//playing
不用在原有的结构里面去添加逻辑判断,通过代理决定是否开放入口来进行实现
总结
模式场景
中间转换参数、保持模块间独立的时候 - 适配器模式
附着于多个组件上,批量动态赋予功能的时候 - 装饰器模式
将代理对象与调用对象分离,不直接调用目标对象 - 代理模式
实际应用
1.两个模块:筛选器和表格,需要做一个联动。但筛选器的数据不能直接传入表格,需要做数据结构转换
=> 模块之间独立,需要做数据结构转换 => 适配器
2.目前有按钮、title、icon三个组件。希望开发一个模块,让三个组件同时具备相同功能 => 套一层装甲对于每个组见
有统一的能力提升,且可以动态添加功能进行拓展 => 装饰器模式
3.ul中多个li,每个li上的点击事件 => 利用冒泡做委托,事件绑定在ul上 => 代理
不同的对象之间划分责任和算法的抽象化
请求以命令的形式包裹在对象中,并传给调用对象
**exm:**对于游戏角色的控制
//接受命令者
class Receiver {
execute() {
console.log('已经在爬了');
}
}
//触发命令者
class Operator {
constructor(command) {
this.command = command;
}
run() {
console.log('给爷爬');
this.command.execute();
}
}
//指令执行者
class Command {
constructor(receiver) {
this.receiver = receiver;
}
execute() {
console.log('执行命令');
this.receiver.execute();
}
}
const soldier = new Receiver();
const order = new Command(soldier);
const player = new Operator(order);
player.run();//给爷爬 执行命令 已经在爬了
每个角色各司其职,通过命令串联起来
在模板中,定义好每个方法的执行步骤。方法本身关注于自己的事情
exm: 想要成功吃个鸡,大概分几步
class Device {
constructor(executePipeLine) {
// executePipeLine…… 可以在里边进行编排
}
powerOn() {
console.log('打开电源');
}
login() {
console.log('登录账号');
}
clickIcon() {
console.log('点击开始游戏');
}
enterGame() {
console.log('进入战场');
}
play() {
this.powerOn();
this.login();
this.clickIcon();
this.enterGame();
}
}
const player = new Device();
player.play();
在类里不光进行了拆解,还进行了编排
当一个属性发生状态改变时,观察者会连续引发所有的相关状态改变
class MediaCenter {
constructor() {
this.state = '';
this.observers = [];
}
attach(observer) {
this.observers.push(observer);
}
getState() {
return this.state;
}
setState(state) {
this.state = state;
this.notifyAllobservers();
}
notifyAllobservers() {
this.observers.forEach(ob => {
ob.update();
})
}
}
class Observer {
constructor(name, center) {
this.name = name;
this.center = center;
this.center.attach(this);
}
update() {
console.log(`${this.name} update, state: ${this.center.getState()}`);
}
}
const center = new MediaCenter();
const ps = new Observer('ps', center);//ps update, state: on
const tv = new Observer('tv', center);//tv update, state: on
center.setState('on');
链式调用 2. 职责独立 3. 顺序执行
exm: 成年高质量男性想要打个游戏,在家里需要过几关
class Action {
constructor(name) {
this.name = name;
this.nextAction = null;
}
setNextAction(action) {
this.nextAction = action;
}
handle() {
console.log(`${this.name}请审批,是否可以打游戏`);
if (this.nextAction !== null) {
this.nextAction.handle();
}
}
}
const dad = new Action('爸');
const mom = new Action('妈');
const wife = new Action('夫人');
dad.setNextAction(mom);
mom.setNextAction(wife);
dad.handle();
//爸请审批,是否可以打游戏
//妈请审批,是否可以打游戏
//夫人请审批,是否可以打游戏
总结
模式场景
发出指令,中间层传递命令本身,命中包含执行对象 - 命令模式
通过模板定义执行顺序,做独立操作 - 模板模式
通过观察者,可以让被观察值统一发生变化,触发相应依赖值的统一更新 - 观察者模式
独立职责的单元通过链式执行,逐步操作流程 - 职责链
实际应用
提交表单进行表单逐行校验,链式调用validate,依次执行 => 职责亮
echart准备工作:canvas、config、init、draw(),规划顺序执行 => 模板模式
调度器在接受到一组新的数据时候,解析数据,并且根据数据类型包裹在对象中传递到下级helper,helper
再去执行相应操作 => 命令模式
输入框输入的值去判断下拉框显示与否 => 观察input设置show => 观察者模式
下机!