前端设计模式
模板方法模式
- 是什么
- 定义算法骨架的设计模式,允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
- 怎么使用
- 创建一个基类,定义一个模板方法,该方法调用由子类实现的抽象方法。
- 应用场景
- 例子
- 在前端开发中,一个基础的表单验证流程可以使用模板方法模式。
class FormValidator {
validate() {
this.validateRequiredFields();
this.validateEmailFormat();
this.validatePasswordStrength();
}
validateRequiredFields() {
throw new Error('This method should be overridden');
}
validateEmailFormat() {
throw new Error('This method should be overridden');
}
validatePasswordStrength() {
throw new Error('This method should be overridden');
}
}
class CustomFormValidator extends FormValidator {
validateRequiredFields() {
console.log('Validating required fields');
}
validateEmailFormat() {
console.log('Validating email format');
}
validatePasswordStrength() {
console.log('Validating password strength');
}
}
const validator = new CustomFormValidator();
validator.validate();
单例模式
- 是什么
- 怎么使用
- 应用场景
- 当需要确保某个类的唯一实例,如全局的应用状态管理器。
- 例子
- Redux 的 store 对象就是一个单例模式的例子。
const Singleton = (function() {
let instance;
function createInstance() {
const object = new Object('I am the instance');
return object;
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2);
工厂模式
- 是什么
- 提供一个接口,创建对象实例,但将具体创建逻辑推迟到子类。
- 怎么使用
- 创建一个工厂类,包含一个创建对象的方法,该方法根据输入返回不同的对象。
- 应用场景
- 当对象的创建逻辑复杂且多样化时,如动态创建不同类型的UI组件。
- 例子
- 在React中,可以有一个组件工厂,动态根据配置创建不同的UI组件。
class Button {
constructor(label) {
this.label = label;
}
render() {
console.log(`<button>${this.label}</button>`);
}
}
class Input {
constructor(placeholder) {
this.placeholder = placeholder;
}
render() {
console.log(`<input placeholder="${this.placeholder}" />`);
}
}
class ComponentFactory {
static createComponent(type, config) {
switch(type) {
case 'button':
return new Button(config.label);
case 'input':
return new Input(config.placeholder);
default:
throw new Error('Unknown component type');
}
}
}
const button = ComponentFactory.createComponent('button', { label: 'Click Me' });
const input = ComponentFactory.createComponent('input', { placeholder: 'Enter text' });
button.render();
input.render();
观察者模式
- 是什么
- 定义对象间的一种一对多的依赖关系,当一个对象状态改变时,所有依赖对象都会收到通知并自动更新。
- 怎么使用
- 定义一个被观察者和多个观察者,被观察者在状态变化时通知所有观察者。
- 应用场景
- 例子
- JavaScript中的事件处理机制,React中的状态管理。
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notifyObservers() {
this.observers.forEach(observer => observer.update());
}
}
class Observer {
update() {
console.log('Observer updated');
}
}
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers();
装饰者模式
- 是什么
- 怎么使用
- 应用场景
- 例子
- 在React中,可以使用高阶组件(HOC)来扩展现有组件的功能。
class Component {
render() {
console.log('Component render');
}
}
class Decorator {
constructor(component) {
this.component = component;
}
render() {
this.component.render();
this.decorate();
}
decorate() {
console.log('Decorated render');
}
}
const component = new Component();
const decoratedComponent = new Decorator(component);
decoratedComponent.render();
策略模式
- 是什么
- 策略模式是一种行为设计模式,定义了一系列算法,将每个算法封装起来,并使它们可以互换。策略模式让算法独立于使用它的客户而变化。
- 怎么使用
- 定义一个策略接口,然后创建实现该接口的具体策略类。在使用策略的类中维护一个对策略对象的引用,并根据需要动态改变策略。
- 应用场景
- 当有多种算法可以实现相同的任务,并且需要在不同的条件下动态选择具体算法时。
- 例子
- 在前端开发中,可以使用策略模式来实现不同的排序算法,根据用户的选择动态切换。
class SortingStrategy {
sort(data) {
throw new Error('This method should be overridden');
}
}
class BubbleSort extends SortingStrategy {
sort(data) {
console.log('Sorting using bubble sort');
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data.length - i - 1; j++) {
if (data[j] > data[j + 1]) {
[data[j], data[j + 1]] = [data[j + 1], data[j]];
}
}
}
return data;
}
}
class QuickSort extends SortingStrategy {
sort(data) {
console.log('Sorting using quick sort');
if (data.length <= 1) return data;
let pivot = data[Math.floor(data.length / 2)];
let left = [];
let right = [];
for (let i = 0; i < data.length; i++) {
if (i !== Math.floor(data.length / 2)) {
data[i] < pivot ? left.push(data[i]) : right.push(data[i]);
}
}
return [...this.sort(left), pivot, ...this.sort(right)];
}
}
class Sorter {
constructor(strategy) {
this.strategy = strategy;
}
setStrategy(strategy) {
this.strategy = strategy;
}
sort(data) {
return this.strategy.sort(data);
}
}
const sorter = new Sorter(new BubbleSort());
let data = [5, 3, 8, 4, 2];
console.log('Original data:', data);
data = sorter.sort(data);
console.log('Sorted data:', data);
sorter.setStrategy(new QuickSort());
data = [5, 3, 8, 4, 2];
console.log('Original data:', data);
data = sorter.sort(data);
console.log('Sorted data:', data);
代理模式
- 是什么
- 代理模式是一种结构型设计模式,允许一个对象(代理)控制对另一个对象(目标对象)的访问。代理模式通常用于延迟处理、控制访问、日志记录、缓存等。
- 怎么使用
- 创建一个代理类,代理类包含对目标对象的引用,并实现与目标对象相同的接口。在代理类中,可以在调用目标对象的方法之前或之后添加额外的功能。
- 应用场景
- 当需要在访问某个对象之前进行额外的操作(如权限检查、延迟初始化、性能优化)时,可以使用代理模式。
- 例子
- 在前端开发中,可以使用代理模式来实现对API请求的缓存。
class APIService {
fetchData() {
console.log('Fetching data from the API');
return new Promise((resolve) => {
setTimeout(() => {
resolve('Data from API');
}, 1000);
});
}
}
class APIServiceProxy {
constructor() {
this.apiService = new APIService();
this.cache = null;
}
async fetchData() {
if (this.cache) {
console.log('Returning cached data');
return Promise.resolve(this.cache);
}
console.log('Fetching data through proxy');
this.cache = await this.apiService.fetchData();
return this.cache;
}
}
(async () => {
const apiProxy = new APIServiceProxy();
let data = await apiProxy.fetchData();
console.log(data);
data = await apiProxy.fetchData();
console.log(data);
})();