工厂模式 ☆
- 将new 操作单独封装
- 遇到new时,就要考虑是否使用工厂模式了
商店封装做汉堡的工作,消费者直接购买汉堡,不用知道具体的生产过程。 示例:
class Product {
constructor(name){
this.name = name
}
init(){}
fn1(){}
}
class Creator {
create(name){
return new Product(name)
}
}
// 测试 根本不用知道Product
let creator = new Create()
let p1 = creator.create('p1')
p1.init
// demo2 React.createElement
class Vnode(tag, attrs, children){
// ...
}
React.createElement = function(tag, attrs, children){
return new Vnode(tag, attrs, children)
}
构造函数和创建者分离,符合开发封闭原则。
单例模式
- 系统中被唯一使用
- 一个类只有一个实例 (obj1 === ojb2) 像登录框、购物车,自执行函数的一种应用
class SingleObject {
login() {
console.log('login ...')
}
xx(){}
}
SingleObject.getInstance = (function(){
let instance
return function(){
if(!instance){
instance = new SingleObject()
}
return instance
}
})()
// test
s1 = SingleObject.getInstance()
s2 = SingleObject.getInstance()
符合单一职责原则,只实例化唯一的对象
适配器模式
- 旧接口格式与使用者不兼容
- 中间加一个适配转换接口,即转换、适配思想
let $ = {
ajax: function(opt){
return ajax(opt)
}
}
$.ajax({}) 就与之前jq的适配了
装饰器模式 es7 装饰器 ☆
- 为对象添加新功能
- 不改变其原有的结构和功能
class Circle {
draw() {}
}
class Decorator {
constructor(circle){
this.circle = circle
}
draw(){
this.circle.draw()
// 装饰
this.addRed(this.circle)
}
addRed(){}
}
ES7 装饰器Demo
@testDec
class Demo {
// ...
}
function testDec(target){
target.isDec = true
}
console.log(Demo.isDec) // true
//2、 也可带参数的装饰器
function testDec(isDec){
return function (target){
target.isDec = isDec
}
}
@testDec(false)
class Demo {
}
console.log(Demo.isDec)
// 3、 装饰类 -- mixin 示例
function mixins(...list){
return function(target){
Object.assign(target.prototype, ...list)
}
}
const Foo = {
foo(){
console.log('foo')
}
}
@mixins(Foo)
class MyClass {}
let obj = new MyClass()
obj.foo()
// 4、 案例
function log(target, name, descriptor){
let oldValue = descriptor.value
descriptor.value = function(){
console.log(`callingxxx`)
return oldValue.apply(this, arguments)
}
return descriptor
}
class Math {
@log
add(a, b){
return a + b
}
}
let math = new Math()
const result = math.add(2,3)
装饰器原理
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A
core-decorators 装饰器类库,封装了常用的来类库。
import { readonly } from 'core-decorators'
class Person {
@readonly
name() {
return 'zhang'
}
}
let p = new Person()
p.name = xxx // 会报错,装饰了readonly.
利用deprecate装饰器给控制台提示信息
import { deprecate } from 'core-decorators'
class Person {
@deprecate('即将弃用')
name() {
return 'xxx'
}
}
将现有对象和装饰器分离。
代理模式
- 使用者无权访问目标对象,中间加代理,通过代理做授权和控制
案例:
class ReadImg {
constructor(fileName){
this.fileName = fileName
}
display(){}
loadImg(){}
}
class ProxyImg {
constructor(fileName){
this.realImg = new ReadImg(fileName)
}
display(){
this.realImg.display()
}
}
明星&经纪人案例
let star = {
name: '张xx',
age: 25,
phone: 123111111
}
let agent = new Proxy(star, {
get: function(target, key){
if(key === 'phone'){
return 'xxx'
}
if(key === 'price'){
return 12000
}
return target[key]
},
set: function(target, key, value){
if(key === 'customPrice'){
if(val < 10000){
throw new Error('价格太低')
} else {
target[key] = val
return true
}
}
}
})
代理类和目录类分离
外观模式
- 为子系统中的一组接口提供一个高层接口
- 使用者使用这个高层接口
观察者模式 ☆
- 发布 & 订阅
- 一对多
class Subject {
constructor(){
this.state = 0
this.observers = []
}
getState(){
return this.state
}
setState(state){
this.state = state
// 通知所有观察者
this.notifyAllObservers()
}
notifyAllObservers(){
this.observers.forEach( observer => {
observer.update()
})
}
attach(observer){
this.observer.push(observer)
}
}
// 观察者
class Observer {
constructor(name, subject){
this.name = name
this.subject = subject
this.subject.attach(this)
}
update(){
console.log(`xxxxx`)
}
}
// 测试
let s = new Subject()
// 2个观察者
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
// demo nodejs 自定义事件
const EventEmitter = require('events').EventEmitter
const emitter1 = new EvevntEmitter()
emitter1.on('some', ()=> {})
emitter1.on('some', ()=> {})
emitter1.emit('some')
// demo2 任何构造函数都可以继承 EventEmitter 的方法 on emit
const EventEmitter = require('events').EventEmitter
class Dog extends EventEmitter {
constructor(name){
super()
this.name = name
}
}
let simon = new Dog('simon')
simon.on('methodsxx', ()=>{
})
simon.emit('methodsxx')
// vue react 生命周期也类似
迭代器模式
- 顺序访问一个集合
- 使用者无需知道集合的内部结构(封装)
class Iterator {
constructor(container){
this.list = container.list
this.index = 0
}
next(){
if(this.hasNext()){
return this.list[this.index++]
}
return null
}
hasNext(){
if(this.index >= this.list.length){
return false
}
return true
}
}
class Container {
constructor(list){
this.list = list
}
// 生成遍历器
getIterator(){
return new Iterator(this)
}
}
let arr = [1,2,3,4,5]
let container = new Container(arr)
let iterator = container.getIterator()
while(iterator.hasNext()){
// xxxx
}
ES6 Iterator 为何存在? es中,有序集合的数据类型有很多。 object 不是有序集合,可以用Map 代替 for(let item of data){} // 遍历迭代器
function each(data){
let iterator = data[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // done {value: undefined, done: true}
let item = {done: false}
while(!item.done){
item = iterator.next()
if(!item.done){
// xxx
}
}
}
Es6 iterator 与Generator
function* helloworld(){
yield 'xx';
yield 'xxx'
return 'ending'
}
状态模式
- 一个对象有状态变化
- 每次状态变化都会触发一个逻辑
class State {
constructor(color){
this.color = color
}
handle(context){
context.setState(this)
}
}
// 主体
class Context {
constructor(){
this.state = null
}
getState(){
return this.state
}
setState(state){
this.state = state
}
}
// 测试
let context = new Context()
let green = new State('green')
// 绿灯亮了
green.handle(context)
Javascript State Machine 库状态管理
var fsm = new StateMachine({
init: 'solid',
transitions: [
{ name: 'melt', from: 'solid', to: 'liquid' },
{ name: 'freeze', from: 'liquid', to: 'solid' },
{ name: 'vaporize', from: 'liquid', to: 'gas' },
{ name: 'condense', from: 'gas', to: 'liquid' }
],
methods: {
onMelt: function() { console.log('I melted') },
onFreeze: function() { console.log('I froze') },
onVaporize: function() { console.log('I vaporized') },
onCondense: function() { console.log('I condensed') }
}
});
单一原则、开放封闭
设计模式案例:
- 单例更多的用在,像弹窗、广告下载组件,保证只new 一次
- 适配器模式, 像对以前的$.ajax 进行适配
let $= {ajax{return aa()}}、 axios 请求参数适配器,对请求的工程参数进行适配
let adaptor = null
if(weex){
adaptor = weexAdaptor
}else if(wechat){
adaptor = wechatAdaptor
}
export default adaptor
- 装饰器模式,原有方法上再挂载其他方法来满足现有需求。像log\readonly 属性