前言
前端在大多数人眼中的理解就是html+css+js,前端框架层出不穷,前端业务也越来越复杂。用健壮的代码来满足复杂的需求变得尤为重要。健壮的代码于我而言,就是变化的好扩展,不变的很稳定。这让我想到了设计模式的SO原则。

每日一学之设计模式
2020.4.1 工厂模式(简单) —— 变与不变(无脑传参)
- 工厂模式就是将创建对象的过程封装起来。
- 通俗的说,就好比你去餐馆吃一顿饭,你点了番茄炒蛋,你不需要关心上菜之前厨师和上菜服务员的任何操作。你只需要关注点菜这个动作。
const map = {
coder: ['code', 'learn'],
UI: ['design']
}
function User(name, age, job, work){
this.name = name;
this.age = age;
this.job = job;
this.work = work;
}
function Factory(name, age, job){
const work = map[job];
return new User(name, age, job, work);
}
2020.4.1 工厂模式(抽象)—— 围绕一个超级工厂创建其他工厂
// 抽象工厂
class MobilePhoneFactory{
createOs(){
throw new Error('抽象方法不能直接调用,你需要将我重写!')
}
createHardWare(){
throw new Error('抽象方法不能直接调用,你需要将我重写')
}
}
// 具体工厂继承抽象工厂
class FakeStarFactory extends MobilePhoneFactory{
createOs(){
// 提供安卓系统实例
return new AndroidOs();
}
createHardWare(){
// 提供高通硬件实例
return new QualcommHardWare();
}
}
// 抽象操作系统产品类
class Os{
controlHardWare(){
throw new Error('抽象产品类不能直接调用,你需要将我重写')
}
}
// 定义具体的产品类
class AndroidOs extends Os{
controlHardWare(){
console.log('我会用安卓的方式去操作硬件')
}
}
class IosOs extends Os{
controlHardWare(){
console.log('我会用的方式去操作硬件')
}
}
// ...抽象硬件产品类同理,
// 定义手机硬件这类产品的抽象产品类
class HardWare {
// 手机硬件的共性方法,这里提取了“根据命令运转”这个共性
operateByOrder() {
throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
}
}
// 定义具体硬件的具体产品类
class QualcommHardWare extends HardWare {
operateByOrder() {
console.log('我会用高通的方式去运转')
}
}
class MiWare extends HardWare {
operateByOrder() {
console.log('我会用小米的方式去运转')
}
}
// 所以你生产一部手机就只需要
const myPhone = new FakeStarFactory(); // new一个手机
const myOs = myPhone.createOs(); // 让它拥有系统
const myHardWare = myPhone.createHardWare(); // 让它拥有硬件
myOs.controlHardWare(); // 启动操作系统,系统去操作硬件
myHardWare.operateByOrder(); // 唤醒硬件
2020.4.7 单例模式 —— 一个实例,全局访问
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
class Single {
show() {
console.log("zzz");
}
static getInstance() {
if (!Single.instance) {
Single.instance = new Single();
}
return Single.instance
}
}
const s1 = Single.getInstance()
const s2 = Single.getInstance()
s1 === s2 // true
2020.4.9 原型模式 —— 用实例来描述对象,用实例作为定义对象和继承的基础
构造函数、构造函数的原型对象和实例对象三个实体之间的关系。 构造函数有prototype属性指向原型对象,原型对象的constructor属性指向构造函数,通过构造函数new的实例对象有_proto_属性指向原型对象。

原型链:

注意关联:对象的深拷贝
2020.4.9 装饰器模式 —— 只添加不修改
function classDecorator(target){
target.hasDecorator = true;
return target;
}
@classDecorator
class Button{
}
console.log('Button 是否被装饰了:', Button.hasDecorator)
// babel转码之后:
'use strict';
var _class;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function classDecorator(target) {
target.hasDecorator = true;
return target;
}
var Button = classDecorator(_class = function Button() {
_classCallCheck(this, Button);
}) || _class;
console.log('Button 是否被装饰了:', Button.hasDecorator);
注意关联:高阶组件
2020.4.14 适配器模式 —— iphoneX的方形耳机孔使用圆形耳机
把变化留给自己,把统一留给用户。统一的入参,统一的出参,统一的规则。
注意关联: axios中的适配器
2020.4.15 代理模式 —— kexue上网
一个对象不能直接访问另一个对象,需要第三者牵线搭桥,实现访问的目的。这个过程就是代理模式。
- 事件代理 —— 比如一个div下面的多个子元素添加点击事件
// 获取父元素
const father = document.getElementById('father')
// 给父元素安装一次监听函数
father.addEventListener('click', function(e) {
// 识别是否是目标子元素
if(e.target.tagName === 'A') {
// 以下是监听函数的函数体
e.preventDefault()
alert(`我是${e.target.innerText}`)
}
} )
2020.4.16 策略模式 —— 拒绝if/else,拆分胖逻辑。
未完待续....