前端要知道的设计模式
2019-06-14 本文已影响0人
chasing_dream
发布订阅模式:
这种设计模式可以大大降低程序没款之间的耦合度,便于更加的灵活的扩展和维护。
// 一个播放器类
class Player {
constructor() {
// 初始化观察者列表
this.watchers = {}
// 模拟2秒后发布一个'play'事件
setTimeout(() => {
this._publish('play', true)
}, 2000)
// 模拟4秒后发布一个'pause'事件
setTimeout(() => {
this._publish('pause', true)
}, 4000)
}
// 发布事件
_publish(event, data) {
if (this.watchers[event] && this.watchers[event].length) {
this.watchers[event].forEach(callback => callback.bind(this)(data))
}
}
// 订阅事件
subscribe(event, callback) {
this.watchers[event] = this.watchers[event] || []
this.watchers[event].push(callback)
}
// 退订事件
unsubscribe(event = null, callback = null) {
// 如果传入指定事件函数,则仅退订此事件函数
if (callback&&event) {
if (this.watchers[event] && this.watchers[event].length) {
this.watchers[event].splice(this.watchers[event].findIndex(cb => Object.is(cb, callback)), 1)
}
// 如果仅传入事件名称,则退订此事件对应的所有的事件函数
} else if (event) {
this.watchers[event] = []
// 如果未传入任何参数,则退订所有事件
} else {
this.watchers = {}
}
}
}
// 实例化播放器
const player = new Player()
console.log(player)
// 播放事件回调函数1
const onPlayerPlay1 = function(data) {
console.log('1: Player is play, the `this` context is current player', this, data)
}
// 播放事件回调函数2
const onPlayerPlay2 = data => {
console.log('2: Player is play', data)
}
// 暂停事件回调函数
const onPlayerPause = data => {
console.log('Player is pause', data)
}
// 加载事件回调函数
const onPlayerLoaded = data => {
console.log('Player is loaded', data)
}
// 可订阅多个不同事件
player.subscribe('play', onPlayerPlay1)
player.subscribe('play', onPlayerPlay2)
player.subscribe('pause', onPlayerPause)
player.subscribe('loaded', onPlayerLoaded)
// 可以退订指定订阅事件
player.unsubscribe('play', onPlayerPlay2)
// 退订指定事件名称下的所有订阅事件
player.unsubscribe('play')
// 退订所有订阅事件
player.unsubscribe()
// 可以在外部手动发出事件(真实生产场景中,发布特性一般为类内部私有方法)
player._publish('loaded', true)
思路:订阅=》添加到watchers(订阅列表)=》执行发布_publish
工厂模式
把相同的操作放在一个对外开放的接口里
代理模式
ES6中的Proxy对象 http://es6.ruanyifeng.com/#docs/proxy
const target = {}
const handler = {
get(target, property) {
if (property in target) {
return target[property]
} else {
throw new ReferenceError("Property \"" + property + "\" does not exist.")
}
}
}
const p = new Proxy(target, {})
p.a = 3 // 被转发到代理的操作
console.log(p.c) //
单例模式/单体模式
//static 如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
http://es6.ruanyifeng.com/#docs/class
// 类数实例:
class Singleton {
constructor(name) {
this.name = name
this.instance = null //
}
getName() {
alert(this.name)
}
static getInstance(name) {
if (!this.instance) {
this.instance = new Singleton(name)
}
return this.instance
}
}
const ins = new Singleton('hhhh')
const instanceA = Singleton.getInstance('seven1')
const instanceB = Singleton.getInstance('seven2')
中介者模式
先来理解这么一个问题,假如我们前端开发接的需求是需求方给我们需求,可能一个前端开发会和多个需求方打交道,所以会保持多个需求方的联系,那么在程序里面就意味着保持多个对象的引用,当程序的规模越大,对象会越来越多,他们之间的关系会越来越复杂,那现在假如现在有一个中介者(假如就是我们的主管)来对接多个需求方的需求,那么需求方只需要把所有的需求给我们主管就可以,主管会依次看我们的工作量来给我们分配任务,这样的话,我们前端开发就不需要和多个业务方联系,我们只需要和我们主管(也就是中介)联系即可,这样的好处就弱化了对象之间的耦合。
function Hero(name) {
this.name = name;
this.enemy = null;
}
Hero.prototype.win = function(){
console.log(this.name + 'Won');
}
Hero.prototype.lose = function(){
console.log(this.name + 'lose');
}
Hero.prototype.die = function(){
this.lose();
this.enemy.win();
}
// 初始化2个对象
var h1 = new Hero("朱元璋");
var h2 = new Hero("刘伯温");
// 给玩家设置敌人
h1.enemy = h2;
h2.enemy = h1;
// 朱元璋死了 也就输了
h1.die(); // 输出 朱元璋lose 刘伯温Won
模块模式
var Person = (function(){
var name = "weixin";
var age = 22;
function getName(){
return name;
}
function getAge(){
return age;
}
return {
getName: getName,
getAge: getAge
}
})();
console.log(age); // 报错:age未定义
console.log(name); // 报错:name未定义
console.log(Person.age); // undefined
console.log(Person.name); // undefined
//只能通过Person提供的接口访问相应的变量
console.log(Person.getName()); // weixin
console.log(Person.getAge()); // 22
构造函数模式
//es5写法
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person;
printName: function(){
console.log(this.name);
},
printAge: function(){
console.log(this.age);
}
}
var person = new Person('xin', 22);
person.printName(); // xin
person.printAge(); // 22
//es6写法
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
printName() {
console.log(this.name);
}
printAge() {
console.log(this.age)
}
}
var person = new Person('xin', 22);
person.printName(); // xin
person.printAge(); // 22
职责链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。(大函数分割成一个个小函数,清晰,各司其职)
优点:代码清晰,可读性较好,拆分函数
//----------------------改造前---------------
var order = function( orderType, pay, stock ){
if ( orderType === 1 ){ // 500 元定金购买模式
if ( pay === true ){ // 已支付定金
console.log( '500 元定金预购, 得到 100 优惠券' );
}else{ // 未支付定金,降级到普通购买模式
if ( stock > 0 ){ // 用于普通购买的手机还有库存
console.log( '普通购买, 无优惠券' );
}else{
console.log( '手机库存不足' );
}
}
}
else if ( orderType === 2 ){ // 200 元定金购买模式
if ( pay === true ){
console.log( '200 元定金预购, 得到 50 优惠券' );
}else{
if ( stock > 0 ){
console.log( '普通购买, 无优惠券' );
}else{
console.log( '手机库存不足' );
}
}
} else if ( orderType === 3 ){
if ( stock > 0 ){
console.log( '普通购买, 无优惠券' );
}else{
console.log( '手机库存不足' );
}
}
};
order( 1 , true, 500); // 输出: 500 元定金预购, 得到 100 优惠券
//--------------------- 改造后----------------------------
// 500 元订单
var order500 = function( orderType, pay, stock ){
if ( orderType === 1 && pay === true ){
console.log( '500 元定金预购, 得到 100 优惠券' );
}else{
order200( orderType, pay, stock ); // 将请求传递给 200 元订单
}
};
// 200 元订单
var order200 = function( orderType, pay, stock ){
if ( orderType === 2 && pay === true ){
console.log( '200 元定金预购, 得到 50 优惠券' );
}else{
orderNormal( orderType, pay, stock ); // 将请求传递给普通订单
}
};
// 普通购买订单
var orderNormal = function( orderType, pay, stock ){
if ( stock > 0 ){
console.log( '普通购买, 无优惠券' );
}else{
console.log( '手机库存不足' );
}
};
// 测试结果:
order500( 1 , true, 500); // 输出:500 元定金预购, 得到 100 优惠券
order500( 1, false, 500 ); // 输出:普通购买, 无优惠券
order500( 2, true, 500 ); // 输出:200 元定金预购, 得到 500 优惠券
order500( 3, false, 500 ); // 输出:普通购买, 无优惠券
order500( 3, false, 0 ); // 输出:手机库存不足
https://segmentfault.com/a/1190000010914032?utm_source=tag-newest
https://blog.csdn.net/song_mou_xia/article/details/80763833
深入理解