前端八股文之设计模式

462 阅读4分钟

目录

待输出

  • 介绍你所理解的中介者模式?
  • 介绍你所理解的装饰器模式?
  • 介绍你所理解的迭代器模式?
  • 介绍你所理解的组合模式?
  • 观察者模式与发布订阅模式的区别
  • 手写一个发布订阅模式
  • 手写一个观察者模式
  • 说一下你所理解的观察者模式?

已完结

  • JS 写一个单例模式,具体的场景
  • 介绍你所理解的单例模式?
  • 介绍你所理解的工厂模式?

JS 写一个单例模式,具体的场景

保证一个类仅有一个实例,并提供一个访问它的全局访问点,一般应用场景:购物车、登录

/*
 * 利用闭包的特性
 * 设置instance
 * if (!instance) 赋值
 * 类返回 instance
*/

// es6
class SingleManage {
	constructor({ name, level }) {
		if (!SingleManage.instance) {
			this.name = name;
			this.level = level;
			SingleManage.instance = this;
		}
		return SingleManage.instance;
	}
}

let boss = new SingleManage({ name: 'zhufeng', level: '1' });
let boss2 = new SingleManage({ name: 'zf', level: '2' });
console.log(boss === boss2);

// es5
function SingleManage(manage) {
	this.name = manage.name;
	this.level = manage.level;
	this.info = function () {
		console.warn("name is " + this.name + ' and level is ' + this.level);
	};
}
SingleManage.getInstance = function (manage) {
	if (!this.instance) {
		this.instance = new SingleManage(manage);
	}
	return this.instance;
};
var boss = SingleManage.getInstance({ name: 'abc', level: '1' });
var boss2 = SingleManage.getInstance({ name: 'def', level: '2' });
boss.info();
boss2.info();

应用实例

// 先实现一个基础的StorageBase类,把getItem和setItem方法放在它的原型链上
function StorageBase() {}
StorageBase.prototype.getItem = function (key) {
	return localStorage.getItem(key);
};
StorageBase.prototype.setItem = function (key, value) {
	return localStorage.setItem(key, value);
};

// 以闭包的形式创建一个引用自由变量的构造函数
const Storage = (function () {
	let instance = null;
	return function () {
		// 判断自由变量是否为null
		if (!instance) {
			// 如果为null则new出唯一实例
			instance = new StorageBase();
		}
		return instance;
	};
})();

// 这里其实不用 new Storage 的形式调用,直接 Storage() 也会有一样的效果
const storage1 = new Storage();
const storage2 = new Storage();

storage1.setItem('name', 'zf');
// zf
storage1.getItem('name');
// zf
storage2.getItem('name');
// 返回true
storage1 === storage2;

介绍你所理解的单例模式?

单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

主要解决

一个全局使用的类频繁地创建与销毁

应用实例

  • 一个班级只有一个班主任。
  • Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
  • 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优点

  • 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
  • 避免对资源的多重占用(比如写文件操作)。

缺点

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

介绍你所理解的工厂模式?

工厂模式是一种用来创建对象的设计模式。我们不暴露对象创建的逻辑,而是将逻辑封装在一个函数内,那么这个函数可以成为工厂。工厂模式根据抽象程度的不同可以分为:

  1. 简单工厂
  2. 工厂方法
  3. 抽象工厂

简单工厂

let factory = function (role) {
	function superman() {
		this.name = '超级管理员';
		this.role = ['修改密码', '发布消息', '查看主页'];
	}

	function commonMan() {
		this.name = '普通游客';
		this.role = ['查看主页'];
	}

	switch (role) {
		case 'superman':
			return new superman();
			break;
		case 'man':
			return new commonMan();
			break;
		default:
			throw new Error('参数错误');
	}
};

let superman = factory('superman');
let man = factory('man');

console.log(superman)
console.log(man)

简单工厂的优点: 你只需要传递一个合法的参数,就可以获取到你想要的对象,而无需知道创建的具体的细节。

但是在函数内包含了所有对象的构造函数和判断逻辑的代码, 每次如果需要添加一个对象,那么我们需要新增一个构造函数,当我们需要维护的对象不是上面这2个,而是20个或者更多,那么这个函数将会成为超级函数,使得我们难以维护。

所以简单工厂模式只适用于在创建时对象数量少,以及逻辑简单的情况。