在前端开发中,设计模式可以帮助我们更好地组织代码、提高可维护性和可扩展性。以下是前端开发中常用的一些设计模式及其具体应用示例。
1. 单例模式(Singleton Pattern)
单例模式确保一个类只有一个实例,并提供一个全局访问点。
示例代码
class Singleton {
static instance = null;
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
this.data = {};
Singleton.instance = this;
}
getData(key) {
return this.data[key];
}
setData(key, value) {
this.data[key] = value;
}
}
const singleton1 = new Singleton();
singleton1.setData('name', 'bob');
const singleton2 = new Singleton();
console.log(singleton2.getData('name')); // 输出 "bob"
2. 工厂模式(Factory Pattern)
工厂模式提供了一种创建对象的接口,但允许子类决定实例化哪个类。
示例代码
function createShape(type) {
switch (type) {
case 'circle':
return new Circle();
case 'square':
return new Square();
default:
throw new Error('Invalid shape type');
}
}
class Shape {
draw() {
console.log('Drawing a shape...');
}
}
class Circle extends Shape {
draw() {
console.log('Drawing a circle...');
}
}
class Square extends Shape {
draw() {
console.log('Drawing a square...');
}
}
const circle = createShape('circle');
circle.draw(); // 输出 "Drawing a circle..."
const square = createShape('square');
square.draw(); // 输出 "Drawing a square..."
3. 观察者模式(Observer Pattern)
观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
示例代码
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
update(data) {
console.log(`Received data: ${data}`);
}
}
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify('Hello, world!'); // 输出 "Received data: Hello, world!"
4. 发布订阅模式(Publish/Subscribe Pattern)
发布订阅模式是一种消息通信模式,对象之间通过事件进行通信。
示例代码
class EventBus {
constructor() {
this.subscribers = {};
}
subscribe(event, callback) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(callback);
}
publish(event, data) {
const callbacks = this.subscribers[event];
if (callbacks) {
callbacks.forEach(callback => callback(data));
}
}
}
const eventBus = new EventBus();
eventBus.subscribe('message', data => console.log(`Received message: ${data}`));
eventBus.publish('message', 'Hello, world!'); // 输出 "Received message: Hello, world!"
5. 模块模式(Module Pattern)
模块模式用于封装私有变量和方法,同时暴露公共接口。
示例代码
const MyModule = (function () {
const privateData = 'Private data';
function privateMethod() {
console.log('Private method called');
}
return {
publicMethod: function () {
console.log('Public method called');
privateMethod();
console.log(privateData);
}
};
})();
MyModule.publicMethod(); // 输出 "Public method called", "Private method called", "Private data"
6. 代理模式(Proxy Pattern)
代理模式为另一个对象提供一个代理或占位符,以便控制对这个对象的访问。
示例代码
class RealSubject {
request() {
console.log('RealSubject: Handling request.');
}
}
class Proxy {
constructor(realSubject) {
this.realSubject = realSubject;
}
request() {
if (this.checkAccess()) {
this.realSubject.request();
}
}
checkAccess() {
console.log('Proxy: Checking access before calling RealSubject.');
return true;
}
}
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);
proxy.request(); // 输出 "Proxy: Checking access befor
7. 装饰器模式(Decorator Pattern) 装饰器本质是函数
装饰器模式允许在不改变对象结构的情况下动态地添加职责。
示例代码
function log(target, key, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args) {
console.log(`Calling ${key} with`, args);
const result = originalMethod.apply(this, args);
console.log(`Called ${key} returned`, result);
return result;
};
return descriptor;
}
class MyClass {
@log
myMethod(message) {
console.log(message);
}
}
const instance = new MyClass();
instance.myMethod('Hello, world!'); // 输出 "Calling myMethod with [ 'Hello, world!' ]", "Hello, world!", "Called myMethod returned undefined"
8. 策略模式(Strategy Pattern)
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。
示例代码
class StrategyA {
execute(data) {
console.log(`Executing strategy A with data: ${data}`);
}
}
class StrategyB {
execute(data) {
console.log(`Executing strategy B with data: ${data}`);
}
}
class Context {
constructor(strategy) {
this.strategy = strategy;
}
setStrategy(strategy) {
this.strategy = strategy;
}
executeStrategy(data) {
this.strategy.execute(data);
}
}
const context = new Context(new StrategyA());
context.executeStrategy('some data'); // 输出 "Executing strategy A with data: some data"
context.setStrategy(new StrategyB());
context.executeStrategy('other data'); // 输出 "Executing strategy B with data: other data"
9. 组合模式(Composite Pattern)
组合模式使得你能够将对象组合成树形结构以表示部分-整体层次结构。
示例代码
class Component {
constructor(name) {
this.name = name;
}
add(component) {
throw new Error('Not implemented');
}
remove(component) {
throw new Error('Not implemented');
}
display(level) {
throw new Error('Not implemented');
}
}
class Leaf extends Component {
display(level) {
console.log(`${' '.repeat(level * 2)}Leaf: ${this.name}`);
}
}
class Composite extends Component {
constructor(name) {
super(name);
this.children = [];
}
add(component) {
this.children.push(component);
}
remove(component) {
this.children = this.children.filter(child => child !== component);
}
display(level) {
console.log(`${' '.repeat(level * 2)}Composite: ${this.name}`);
this.children.forEach(child => child.display(level + 1));
}
}
const root = new Composite('root');
const leaf1 = new Leaf('leaf1');
const leaf2 = new Leaf('leaf2');
const composite1 = new Composite('composite1');
const leaf3 = new Leaf('leaf3');
root.add(leaf1);
root.add(composite1);
composite1.add(leaf2);
composite1.add(leaf3);
root.display(0); // 输出 "Composite: root", " Leaf: leaf1", " Composite: composite1", " Leaf: leaf2", " Leaf: leaf3"
10. 责任链模式(Chain of Responsibility Pattern)
责任链模式使得多个对象有机会处理请求,直到其中一个对象处理为止。
示例代码
class Handler {
constructor(successor) {
this.successor = successor;
}
handleRequest(request) {
if (this.successor) {
this.successor.handleRequest(request);
}
}
}
class ConcreteHandler1 extends Handler {
handleRequest(request) {
if (request === 1) {
console.log('ConcreteHandler1 handled request');
} else {
super.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
handleRequest(request) {
if (request === 2) {
console.log('ConcreteHandler2 handled request');
} else {
super.handleRequest(request);
}
}
}
class ConcreteHandler3 extends Handler {
handleRequest(request) {
if (request === 3) {
console.log('ConcreteHandler3 handled request');
} else {
super.handleRequest(request);
}
}
}
const handler1 = new ConcreteHandler1(new ConcreteHandler2(new ConcreteHandler3(null)));
handler1.handleRequest(1); // 输出 "ConcreteHandler1 handled request"
handler1.handleRequest(2); // 输出 "ConcreteHandler2 handled request"
handler1.handleRequest(3); // 输出 "ConcreteHandler3 handled request"
举例说明实际开发类库中用到比较多的
1. 观察者模式(Observer Pattern)
观察者模式在前端框架中非常常见,特别是在响应式数据绑定和事件驱动的场景中。
应用场景
- Vue.js:Vue.js 使用观察者模式来实现数据的双向绑定。
- React:虽然 React 不直接使用观察者模式,但它通过
useEffect
钩子实现了类似的功能。
示例代码(Vue.js)
// Vue.js 实现中的简单观察者模式
class Observer {
constructor(value) {
this.value = value;
this.walk(value);
}
walk(obj) {
Object.keys(obj).forEach(key => {
this.defineReactive(obj, key, obj[key]);
});
}
defineReactive(obj, key, val) {
this.observe(val);
Object.defineProperty(obj, key, {
get() {
console.log(`Getting ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`Setting ${key}: ${newVal}`);
val = newVal;
}
}
});
}
observe(val) {
if (val && typeof val === 'object') {
new Observer(val);
}
}
}
const data = { message: 'Hello Vue!' };
const observer = new Observer(data);
data.message = 'Updated message'; // 输出 "Setting message: Updated message"
console.log(data.message); // 输出 "Updated message"
2. 发布订阅模式(Publish/Subscribe Pattern)
发布订阅模式在前端框架中用于事件管理和异步通信。
应用场景
- Vue.js:Vue.js 中的事件总线(Event Bus)。
- Angular:RxJS 库中的 Observable。
- React:Redux 中的中间件(如
redux-saga
)。
示例代码(Vue.js 事件总线)
// Vue.js 事件总线实现
class EventBus {
constructor() {
this.subscribers = {};
}
$on(event, callback) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(callback);
}
$emit(event, ...args) {
const callbacks = this.subscribers[event];
if (callbacks) {
callbacks.forEach(callback => callback(...args));
}
}
}
const eventBus = new EventBus();
eventBus.$on('message', data => console.log(`Received message: ${data}`));
eventBus.$emit('message', 'Hello, world!'); // 输出 "Received message: Hello, world!"
3. 单例模式(Singleton Pattern)
单例模式用于确保全局唯一实例,常用于状态管理和其他全局服务。
应用场景
- Redux:全局状态管理。
- Vuex:Vue.js 的状态管理库。
示例代码(Redux)
// Redux 中的单例模式
import { createStore } from 'redux';
const initialState = {
count: 0
};
function reducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
default:
return state;
}
}
const store = createStore(reducer);
store.subscribe(() => {
console.log(store.getState());
});
store.dispatch({ type: 'INCREMENT' }); // 输出 "{ count: 1 }"
store.dispatch({ type: 'INCREMENT' }); // 输出 "{ count: 2 }"
4. 工厂模式(Factory Pattern)
工厂模式用于创建对象的接口,常用于组件工厂和其他创建逻辑。
应用场景
- React:组件工厂。
- Vue.js:组件工厂。
示例代码(React 组件工厂)
// React 组件工厂
function createComponent(type) {
switch (type) {
case 'button':
return <button>Button</button>;
case 'input':
return <input type="text" />;
default:
throw new Error('Invalid component type');
}
}
const button = createComponent('button');
const input = createComponent('input');
console.log(button); // 输出 "<button>Button</button>"
console.log(input); // 输出 "<input type="text" />"
5. 装饰器模式(Decorator Pattern)
装饰器模式用于动态地添加功能,常用于增强类的功能。
应用场景
- React:高阶组件(Higher-Order Components)。
- Vue.js:装饰器(如
@watch
)。
示例代码(React 高阶组件)
// React 高阶组件
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log('Component mounted');
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
class Button extends React.Component {
render() {
return <button>{this.props.children}</button>;
}
}
const LoggingButton = withLogging(Button);
ReactDOM.render(<LoggingButton>Click me</LoggingButton>, document.getElementById('root'));
6. 策略模式(Strategy Pattern)
策略模式用于封装一系列算法,常用于不同的策略实现。
应用场景
- Vue.js:路由守卫(Route Guards)。
- React:路由配置(Route Configurations)。
示例代码(Vue.js 路由守卫)
// Vue.js 路由守卫
const authGuard = to => {
if (isAuthenticated()) {
return true;
}
return '/login';
};
const guestGuard = to => {
if (!isAuthenticated()) {
return true;
}
return '/';
};
const router = new VueRouter({
routes: [
{ path: '/', component: HomeComponent, beforeEnter: guestGuard },
{ path: '/dashboard', component: DashboardComponent, beforeEnter: authGuard }
]
});
7. 适配器模式(Adapter Pattern)
适配器模式用于适配不同的接口,常用于第三方库的集成。
应用场景
- Vue.js:适配不同数据源。
- React:适配不同 API。
示例代码(Vue.js 适配器)
// Vue.js 适配器
class ThirdPartyAPI {
fetchData() {
return Promise.resolve({ data: 'Third party data' });
}
}
class AdapterAPI {
constructor(api) {
this.api = api;
}
fetchCustomData() {
return this.api.fetchData().then(response => ({
customData: response.data
}));
}
}
const thirdPartyAPI = new ThirdPartyAPI();
const adapterAPI = new AdapterAPI(thirdPartyAPI);
adapterAPI.fetchCustomData().then(data => console.log(data)); // 输出 "{ customData: 'Third party data' }"
总结
- 单例模式:确保一个类只有一个实例。
- 工厂模式:创建对象的接口。
- 观察者模式:对象之间的一对多依赖关系。
- 发布订阅模式:基于事件的消息通信。
- 模块模式:封装私有变量和方法。
- 代理模式:为另一个对象提供代理。
- 装饰器模式:动态地添加职责。
- 命令模式:封装请求。
- 策略模式:封装一系列算法。
- 适配器模式:使不兼容的接口匹配。
- 组合模式:表示部分-整体层次结构。
- 责任链模式:多个对象处理请求。
- 状态模式:对象在内部状态改变时改变行为。
以上是前端开发中常用的一些设计模式及其具体应用示例。通过这些设计模式,我们可以更好地组织代码,提高代码的可维护性和可扩展性。每种模式都有其特定的应用场景,选择合适的设计模式可以显著提升代码质量和开发效率。