前端设计模式
模板方法模式
是什么
定义算法骨架的设计模式,允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
怎么使用
创建一个基类,定义一个模板方法,该方法调用由子类实现的抽象方法。
应用场景
例子
在前端开发中,一个基础的表单验证流程可以使用模板方法模式。
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) ;
} ) ( ) ;