初识设计模式,设计模式在js(ts)中的应用(一)

171 阅读4分钟

设计模式的分类

一、创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

二、结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

三、行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

一、工厂模式

定义

封装一个类,通过这个类实例化我们的对象

例子

下面这个例子当中,我们有一个产品类,一个工厂类。 产品类当中,有产品的属性以及方法。 工厂类当中,存在生产产品的方法。 我们实例化一个工厂,然后通过这个工厂来生产产品。

class Product{
	constructor(name){
		this.name = name
	}
	init(){
		alert(‘init’)
	}
	fun1(){
		alert(‘fun1’)
	}
}
class Creator{
        create(name){
		return new Product(name)
	}
}
let creator = new Creator();
let p = creator.create(‘p1’)

常见场景

1.jQuery中的$('div')方法

如果用原来的new方法去创建jQuery对象,就无法进行链式调用

采用工厂模式,让jQuery可以形成链式调用

class jQuery{
    constructor(selector){
        ....
    }
    append(node){...}
    addClass(name){...}
    html(data){...}
}
window.$ = function(selector){
    return new jQuery(selector)
}

2.React.createElement

React创建虚拟dom的实例

React.createElement("div",null,
    React.createElement("img",{ src: "aatar.png", className: "profile" }),
    React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
);
class Vnode(tag, attrs, children){...}
React.createElement = function (tag, attrs, children) {
    return new Vnode(tag, attrs, children)
}

设计原则

1.构造函数和创建者分离

2.符合开放封闭原则

二、单例模式

定义

一个类只有一个实例

例子

需要用到private特性,外部无法new这个对象。js无法实现,但是现在可以通过ts实现。

class SingleObject{
	// 将构造函数私有化,外部就无法直接实例化
	private constructor(){		
	}
	// 对象唯一实例,且不允许外部更改
	private instance:SingleObject = null;
	public getInstance(){
		if(this.instance === null) {
			// 只创造一次实例
			return new SingleObject();
		}
		return this.instance;
	}
	// 实例上的方法
	public login = (username:string, password:string) => {
		// ...
	}
}

常见场景

1.jQuery只有一个$

if(window.jQuery !== null) {
    return window.jQuery
} else {
    // 初始化
}

2.模态框

我们平常所使用的模态框一般一个功能用的都是同一个。对模态框一般采用的都是显示、隐藏,而非重复的创造、销毁。

3.vuex和redux中的store

整个vue当中使用的store对象都是同一个,如果各个页面用的store对象不同,也就无法实现数据同步互相通信了。

设计原则

1.符合单一职责原则,只实例化唯一的对象

2.没法具体开放封闭原则,但是绝对不违反开放封闭原则

三、适配器模式

定义

旧接口的格式和我现在的使用场景不兼容或者不适用,通过一个中间转换来转换接口。

例子

下面这个例子只是简单的示范

class OldProduct{
	public a: string;
	public sum: number;
	constructor(a: string, sum: number){
		this.a = a;
		this.sum = sum;
	}
}
class Adaptor {
	adapte(a:string,num1:number,num2:number){
		return new OldProduct(a,num1+num2);
	}
}
let adapte = new Adaptor();
let newProduct = adapte.adapte('a',1,2);

常见场景

1.二次封装组件

在react和vue开发过程当中经常会出现组件当前虽然在当前场景可以使用,但是使用起来很复杂,逻辑和当前业务不适配。所以,这个时候就可以对组件二次封装,将组件的配置项做一个改造,这样一来,就可以简化我们的开发,提高开发效率。

  1. vue computed

computed其实使用到的就是适配器模式的思想,原先的数据可能不适用当前场景,通过computed,来进行一个转化,形成我们所想要的样子。

image.png

设计原则

1.将旧接口和使用者进行分离

2.符合开放封闭原则

四、装饰器模式

定义

在不改变原有对象的结构和功能的基础上,为对象添加新功能

例子

class Circle {
	draw() {
		console.log('画一个圆形')
	}
}
class Decorator {
	public circle
	constructor(circle) {
		this.circle = circle
	}
	draw() {
		this.circle.draw()
	}
	// 添加一个边框变红的功能
	setRedBorder(){
		console.log('设置红色边框')
	}
}
let circle = new Circle()
circle.draw()

let dec = new Decorator(circle)
dec.draw()
dec.setRedBorder()

常见场景

  1. ES7的装饰器语法(mobx开发中常用)
@testDec
class Demo{...}
function testDec(target) {
    target.isDec = true;
}
alert(Demo.isDec);
  1. 组件二次封装添加新功能

一般开发当中,如果当前组件不满足我们的需求,就可以通过二次封装,新增新的功能。一般还会结合适配器模式,对配置项进行适配改造。

3.core-decorators

一个第三方开源lib,提供常用的装饰器

文档地址:github.com/jayphelps/c…

设计原则

1.将现有对象和装饰器进行分离,两者独立存在

2.符合开放封闭原则