前端设计模式全面解析
一、设计模式概述
1.1 什么是设计模式
设计模式是针对特定上下文的常见问题的可重用解决方案。在前端开发中,它们帮助我们构建可维护、可扩展、可重用的代码。
1.2 设计模式分类
- 创建型模式:处理对象创建机制
- 结构型模式:处理对象组合方式
- 行为型模式:处理对象间的通信和责任分配
二、创建型模式
2.1 工厂模式(Factory Pattern)
将对象创建逻辑封装起来。
javascript
// 简单工厂
class ButtonFactory {
createButton(type) {
switch(type) {
case 'primary':
return new PrimaryButton();
case 'secondary':
return new SecondaryButton();
default:
throw new Error('Unknown button type');
}
}
}
// 工厂方法
class Dialog {
createButton() {} // 抽象方法
render() {
const button = this.createButton();
button.render();
}
}
class WindowsDialog extends Dialog {
createButton() {
return new WindowsButton();
}
}
class WebDialog extends Dialog {
createButton() {
return new WebButton();
}
}
2.2 建造者模式(Builder Pattern)
分步骤构建复杂对象。
javascript
class Car {
constructor() {
this.engine = null;
this.seats = 0;
this.gps = false;
}
toString() {
return `Car with ${this.engine} engine, ${this.seats} seats, GPS: ${this.gps}`;
}
}
class CarBuilder {
constructor() {
this.car = new Car();
}
setEngine(engine) {
this.car.engine = engine;
return this;
}
setSeats(seats) {
this.car.seats = seats;
return this;
}
setGPS(hasGPS) {
this.car.gps = hasGPS;
return this;
}
build() {
return this.car;
}
}
// 使用
const car = new CarBuilder()
.setEngine('V8')
.setSeats(4)
.setGPS(true)
.build();
console.log(car.toString());
2.3 单例模式(Singleton Pattern)
确保一个类只有一个实例。
javascript
class Singleton {
static #instance = null;
constructor() {
if (Singleton.#instance) {
return Singleton.#instance;
}
Singleton.#instance = this;
// 初始化代码
this.config = {};
}
static getInstance() {
if (!Singleton.#instance) {
Singleton.#instance = new Singleton();
}
return Singleton.#instance;
}
setConfig(key, value) {
this.config[key] = value;
}
getConfig(key) {
return this.config[key];
}
}
// 使用
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
2.4 原型模式(Prototype Pattern)
通过克隆现有对象创建新对象。
javascript
class ComponentPrototype {
constructor(name, styles = {}) {
this.name = name;
this.styles = styles;
this.children = [];
}
clone() {
const clone = new ComponentPrototype(this.name);
clone.styles = { ...this.styles };
clone.children = [...this.children];
return clone;
}
addChild(child) {
this.children.push(child);
}
render() {
console.log(`Rendering ${this.name} with styles:`, this.styles);
}
}
// 使用
const baseButton = new ComponentPrototype('Button', {
color: 'blue',
padding: '10px'
});
const primaryButton = baseButton.clone();
primaryButton.name = 'Primary Button';
primaryButton.styles.color = 'green';
const secondaryButton = baseButton.clone();
secondaryButton.styles.color = 'gray';
三、结构型模式
3.1 适配器模式(Adapter Pattern)
让不兼容的接口能够一起工作。
javascript
// 旧系统
class OldPaymentSystem {
processPayment(amountInDollars) {
console.log(`Processing $${amountInDollars} payment`);
return true;
}
}
// 新系统(期望欧元)
class NewPaymentSystem {
processPayment(amountInEuros) {
console.log(`Processing €${amountInEuros} payment`);
return true;
}
}
// 适配器
class PaymentAdapter {
constructor(oldSystem) {
this.oldSystem = oldSystem;
}
processPayment(amountInEuros) {
// 转换欧元为美元
const amountInDollars = amountInEuros * 1.2;
return this.oldSystem.processPayment(amountInDollars);
}
}
// 使用
const oldSystem = new OldPaymentSystem();
const adapter = new PaymentAdapter(oldSystem);
adapter.processPayment(100); // 转换为 $120
3.2 装饰器模式(Decorator Pattern)
动态添加功能到对象。
javascript
// 基础组件
class TextComponent {
constructor(text) {
this.text = text;
}
render() {
return this.text;
}
}
// 装饰器基类
class TextDecorator {
constructor(component) {
this.component = component;
}
render() {
return this.component.render();
}
}
// 具体装饰器
class BoldDecorator extends TextDecorator {
render() {
return `<b>${super.render()}</b>`;
}
}
class ItalicDecorator extends TextDecorator {
render() {
return `<i>${super.render()}</i>`;
}
}
class LinkDecorator extends TextDecorator {
constructor(component, url) {
super(component);
this.url = url;
}
render() {
return `<a href="${this.url}">${super.render()}</a>`;
}
}
// 使用
let text = new TextComponent('Hello World');
text = new BoldDecorator(text);
text = new ItalicDecorator(text);
text = new LinkDecorator(text, 'https://example.com');
console.log(text.render());
// <a href="https://example.com"><i><b>Hello World</b></i></a>
3.3 代理模式(Proxy Pattern)
控制对对象的访问。
javascript
// 真实对象
class ImageLoader {
constructor(filename) {
this.filename = filename;
this.loadImage();
}
loadImage() {
console.log(`Loading image: ${this.filename}`);
// 模拟耗时的加载
this.image = `Image data for ${this.filename}`;
}
display() {
console.log(`Displaying: ${this.image}`);
}
}
// 代理
class ImageProxy {
constructor(filename) {
this.filename = filename;
this.realImage = null;
}
display() {
if (!this.realImage) {
this.realImage = new ImageLoader(this.filename);
}
this.realImage.display();
}
}
// 使用
const image1 = new ImageProxy('photo1.jpg');
const image2 = new ImageProxy('photo2.jpg');
// 图片不会立即加载
image1.display(); // 加载并显示
image1.display(); // 直接显示(已缓存)
image2.display(); // 加载并显示
3.4 外观模式(Facade Pattern)
简化复杂系统的接口。
javascript
// 复杂子系统
class CPU {
freeze() { console.log('CPU freeze'); }
jump(position) { console.log(`CPU jump to ${position}`); }
execute() { console.log('CPU execute'); }
}
class Memory {
load(position, data) {
console.log(`Memory load ${data} at ${position}`);
}
}
class HardDrive {
read(lba, size) {
const data = `data from sector ${lba}`;
console.log(`HardDrive read: ${data}`);
return data;
}
}
// 外观
class ComputerFacade {
constructor() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
start() {
console.log('Computer starting...');
this.cpu.freeze();
const bootData = this.hardDrive.read(0, 1024);
this.memory.load(0x0, bootData);
this.cpu.jump(0x0);
this.cpu.execute();
console.log('Computer started!');
}
}
// 使用
const computer = new ComputerFacade();
computer.start();
3.5 组合模式(Composite Pattern)
以树形结构组合对象。
javascript
// 组件接口
class UIComponent {
constructor(name) {
this.name = name;
this.children = [];
}
add(component) {
this.children.push(component);
}
remove(component) {
const index = this.children.indexOf(component);
if (index > -1) {
this.children.splice(index, 1);
}
}
render() {
console.log(`Rendering ${this.name}`);
this.children.forEach(child => child.render());
}
}
// 叶子节点
class Button extends UIComponent {
constructor(name) {
super(name);
}
render() {
console.log(`[Button] ${this.name}`);
}
}
class Input extends UIComponent {
constructor(name) {
super(name);
}
render() {
console.log(`[Input] ${this.name}`);
}
}
// 使用
const form = new UIComponent('Login Form');
const usernameInput = new Input('Username');
const passwordInput = new Input('Password');
const submitButton = new Button('Submit');
form.add(usernameInput);
form.add(passwordInput);
form.add(submitButton);
const panel = new UIComponent('Main Panel');
panel.add(form);
panel.render();
四、行为型模式
4.1 观察者模式(Observer Pattern)
对象间的一对多依赖关系。
javascript
// 观察者接口
class Observer {
update(data) {}
}
// 主题
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
// 具体观察者
class UserInterface extends Observer {
constructor(name) {
super();
this.name = name;
}
update(data) {
console.log(`${this.name} received:`, data);
}
}
// 使用
const newsPublisher = new Subject();
const ui1 = new UserInterface('Mobile App');
const ui2 = new UserInterface('Web Dashboard');
const ui3 = new UserInterface('Email Service');
newsPublisher.subscribe(ui1);
newsPublisher.subscribe(ui2);
newsPublisher.subscribe(ui3);
newsPublisher.notify('New product launched!');
newsPublisher.unsubscribe(ui2);
newsPublisher.notify('Special discount available!');
4.2 发布-订阅模式(Pub/Sub Pattern)
观察者模式的变体,使用消息通道。
javascript
class EventBus {
constructor() {
this.events = {};
}
subscribe(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
unsubscribe(event, callback) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
publish(event, data) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(data));
}
}
// 使用
const bus = new EventBus();
// 订阅者
const logger = data => console.log(`[LOG] ${data}`);
const notifier = data => console.log(`[NOTIFY] ${data}`);
const analyzer = data => console.log(`[ANALYZE] ${JSON.stringify(data)}`);
// 订阅事件
bus.subscribe('user.login', logger);
bus.subscribe('user.login', notifier);
bus.subscribe('user.purchase', analyzer);
// 发布事件
bus.publish('user.login', { username: 'john', time: new Date() });
bus.publish('user.purchase', { item: 'Book', price: 29.99 });
4.3 策略模式(Strategy Pattern)
定义一系列算法,使它们可以互换。
javascript
// 策略接口
class PaymentStrategy {
pay(amount) {}
}
// 具体策略
class CreditCardPayment extends PaymentStrategy {
constructor(cardNumber, cvv) {
super();
this.cardNumber = cardNumber;
this.cvv = cvv;
}
pay(amount) {
console.log(`Paid $${amount} with credit card ${this.cardNumber}`);
}
}
class PayPalPayment extends PaymentStrategy {
constructor(email) {
super();
this.email = email;
}
pay(amount) {
console.log(`Paid $${amount} with PayPal ${this.email}`);
}
}
class CryptoPayment extends PaymentStrategy {
constructor(walletAddress) {
super();
this.walletAddress = walletAddress;
}
pay(amount) {
console.log(`Paid $${amount} with crypto to ${this.walletAddress}`);
}
}
// 上下文
class ShoppingCart {
constructor() {
this.items = [];
this.paymentStrategy = null;
}
addItem(item, price) {
this.items.push({ item, price });
}
setPaymentStrategy(strategy) {
this.paymentStrategy = strategy;
}
checkout() {
const total = this.items.reduce((sum, item) => sum + item.price, 0);
console.log(`Total: $${total}`);
if (this.paymentStrategy) {
this.paymentStrategy.pay(total);
this.items = [];
} else {
throw new Error('Payment strategy not set');
}
}
}
// 使用
const cart = new ShoppingCart();
cart.addItem('Book', 25);
cart.addItem('Mouse', 40);
cart.setPaymentStrategy(new CreditCardPayment('1234-5678-9012-3456', '123'));
cart.checkout();
cart.addItem('Keyboard', 80);
cart.setPaymentStrategy(new PayPalPayment('john@example.com'));
cart.checkout();
4.4 状态模式(State Pattern)
对象内部状态改变时改变其行为。
javascript
// 状态接口
class OrderState {
constructor(order) {
this.order = order;
}
next() {}
previous() {}
cancel() {}
}
// 具体状态
class PendingState extends OrderState {
next() {
this.order.setState(new ProcessingState(this.order));
console.log('Order moved to processing');
}
cancel() {
this.order.setState(new CancelledState(this.order));
console.log('Order cancelled');
}
}
class ProcessingState extends OrderState {
next() {
this.order.setState(new ShippedState(this.order));
console.log('Order shipped');
}
previous() {
this.order.setState(new PendingState(this.order));
console.log('Order moved back to pending');
}
}
class ShippedState extends OrderState {
next() {
this.order.setState(new DeliveredState(this.order));
console.log('Order delivered');
}
previous() {
this.order.setState(new ProcessingState(this.order));
console.log('Order moved back to processing');
}
}
class DeliveredState extends OrderState {
// 最终状态
}
class CancelledState extends OrderState {
// 最终状态
}
// 上下文
class Order {
constructor() {
this.state = new PendingState(this);
}
setState(state) {
this.state = state;
}
next() {
this.state.next();
}
previous() {
this.state.previous();
}
cancel() {
this.state.cancel();
}
}
// 使用
const order = new Order();
order.next(); // Pending -> Processing
order.next(); // Processing -> Shipped
order.next(); // Shipped -> Delivered
const order2 = new Order();
order2.next(); // Pending -> Processing
order2.cancel(); // Processing -> Cancelled
4.5 命令模式(Command Pattern)
将请求封装为对象。
javascript
// 命令接口
class Command {
execute() {}
undo() {}
}
// 具体命令
class LightOnCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.turnOn();
}
undo() {
this.light.turnOff();
}
}
class ThermostatUpCommand extends Command {
constructor(thermostat) {
super();
this.thermostat = thermostat;
this.previousTemp = 0;
}
execute() {
this.previousTemp = this.thermostat.getTemperature();
this.thermostat.setTemperature(this.previousTemp + 2);
}
undo() {
this.thermostat.setTemperature(this.previousTemp);
}
}
// 接收者
class Light {
turnOn() {
console.log('Light is ON');
}
turnOff() {
console.log('Light is OFF');
}
}
class Thermostat {
constructor() {
this.temperature = 20;
}
getTemperature() {
return this.temperature;
}
setTemperature(temp) {
this.temperature = temp;
console.log(`Thermostat set to ${temp}°C`);
}
}
// 调用者
class RemoteControl {
constructor() {
this.commands = [];
this.history = [];
}
setCommand(command) {
this.commands.push(command);
}
pressButton(index) {
if (index < this.commands.length) {
const command = this.commands[index];
command.execute();
this.history.push(command);
}
}
pressUndo() {
if (this.history.length > 0) {
const command = this.history.pop();
command.undo();
}
}
}
// 使用
const remote = new RemoteControl();
const light = new Light();
const thermostat = new Thermostat();
const lightOn = new LightOnCommand(light);
const tempUp = new ThermostatUpCommand(thermostat);
remote.setCommand(lightOn);
remote.setCommand(tempUp);
remote.pressButton(0); // Light on
remote.pressButton(1); // Temperature up
remote.pressUndo(); // Temperature down
remote.pressUndo(); // Light off
五、前端特定模式
5.1 模块模式(Module Pattern)
使用闭包创建私有作用域。
javascript
const UserModule = (function() {
// 私有变量
let users = [];
let userCount = 0;
// 私有方法
function generateId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
// 公共接口
return {
addUser(name, email) {
const user = {
id: generateId(),
name,
email,
createdAt: new Date()
};
users.push(user);
userCount++;
return user.id;
},
getUser(id) {
return users.find(user => user.id === id);
},
getAllUsers() {
return [...users];
},
getUserCount() {
return userCount;
},
// 仅返回公开数据
getPublicUserData(id) {
const user = this.getUser(id);
if (user) {
const { email, ...publicData } = user;
return publicData;
}
return null;
}
};
})();
// 使用
const userId = UserModule.addUser('John', 'john@example.com');
console.log(UserModule.getPublicUserData(userId));
5.2 混入模式(Mixin Pattern)
通过组合扩展类功能。
javascript
// Mixins
const Loggable = Base => class extends Base {
log(message) {
console.log(`[${this.constructor.name}] ${message}`);
}
};
const Serializable = Base => class extends Base {
serialize() {
return JSON.stringify(this);
}
static deserialize(json) {
const data = JSON.parse(json);
return new this(data);
}
};
const Validatable = Base => class extends Base {
validate() {
const errors = [];
// 检查必需字段
if (this.requiredFields) {
this.requiredFields.forEach(field => {
if (!this[field]) {
errors.push(`${field} is required`);
}
});
}
return {
isValid: errors.length === 0,
errors
};
}
};
// 基础类
class Model {
constructor(data = {}) {
Object.assign(this, data);
}
save() {
console.log('Saving model...');
}
}
// 应用Mixins
class User extends Serializable(Validatable(Loggable(Model))) {
constructor(data) {
super(data);
this.requiredFields = ['name', 'email'];
}
}
// 使用
const user = new User({
name: 'John Doe',
email: 'john@example.com'
});
user.log('Created user');
console.log(user.validate());
const json = user.serialize();
const user2 = User.deserialize(json);
5.3 中间件模式(Middleware Pattern)
处理请求的管道。
javascript
class MiddlewarePipeline {
constructor() {
this.middlewares = [];
}
use(middleware) {
this.middlewares.push(middleware);
}
async execute(context, finalHandler) {
let index = -1;
const dispatch = async i => {
if (i <= index) {
throw new Error('next() called multiple times');
}
index = i;
let fn = this.middlewares[i];
if (i === this.middlewares.length) {
fn = finalHandler;
}
if (!fn) {
return;
}
await fn(context, () => dispatch(i + 1));
};
return dispatch(0);
}
}
// 使用示例:HTTP请求处理
const pipeline = new MiddlewarePipeline();
// 中间件
pipeline.use(async (ctx, next) => {
console.log('Middleware 1: Logging request');
ctx.startTime = Date.now();
await next();
const duration = Date.now() - ctx.startTime;
console.log(`Middleware 1: Request took ${duration}ms`);
});
pipeline.use(async (ctx, next) => {
console.log('Middleware 2: Authentication');
ctx.user = { id: 1, name: 'John' };
await next();
});
pipeline.use(async (ctx, next) => {
console.log('Middleware 3: Authorization');
if (!ctx.user) {
throw new Error('Unauthorized');
}
await next();
});
// 最终处理函数
async function finalHandler(ctx) {
console.log('Final handler: Processing request');
console.log('User:', ctx.user);
ctx.response = { success: true, data: 'Some data' };
}
// 执行
const context = { request: { url: '/api/data' } };
pipeline.execute(context, finalHandler)
.then(() => console.log('Response:', context.response))
.catch(err => console.error('Error:', err.message));
5.4 组件模式(Component Pattern)
javascript
// 基础组件类
class Component {
constructor(props = {}) {
this.props = props;
this.state = {};
this.children = [];
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.render();
}
addChild(child) {
this.children.push(child);
}
render() {
throw new Error('render() must be implemented');
}
mount(container) {
this.container = container;
this.render();
}
}
// 具体组件
class Button extends Component {
constructor(props) {
super(props);
this.state = { clicked: false };
}
handleClick = () => {
this.setState({ clicked: true });
if (this.props.onClick) {
this.props.onClick();
}
};
render() {
const button = document.createElement('button');
button.textContent = this.props.label || 'Click me';
button.style.backgroundColor = this.state.clicked ? 'green' : 'blue';
button.style.color = 'white';
button.style.padding = '10px 20px';
button.onclick = this.handleClick;
if (this.container) {
this.container.innerHTML = '';
this.container.appendChild(button);
}
return button;
}
}
class Form extends Component {
render() {
const form = document.createElement('form');
form.style.padding = '20px';
form.style.border = '1px solid #ccc';
this.children.forEach(child => {
const element = child.render();
form.appendChild(element);
});
if (this.container) {
this.container.innerHTML = '';
this.container.appendChild(form);
}
return form;
}
}
// 使用
const submitButton = new Button({
label: 'Submit',
onClick: () => console.log('Submitted!')
});
const cancelButton = new Button({
label: 'Cancel',
onClick: () => console.log('Cancelled!')
});
const form = new Form();
form.addChild(submitButton);
form.addChild(cancelButton);
// 挂载到DOM
form.mount(document.getElementById('app'));
六、React/Vue中的设计模式
6.1 高阶组件(HOC)- React
jsx
// 高阶组件
const withLoading = (WrappedComponent) => {
return function WithLoadingComponent({ isLoading, ...props }) {
if (isLoading) {
return <div className="loading">Loading...</div>;
}
return <WrappedComponent {...props} />;
};
};
const withError = (WrappedComponent) => {
return function WithErrorComponent({ error, ...props }) {
if (error) {
return <div className="error">Error: {error.message}</div>;
}
return <WrappedComponent {...props} />;
};
};
// 使用
const DataDisplay = ({ data }) => (
<div className="data">{JSON.stringify(data)}</div>
);
const EnhancedDataDisplay = withError(withLoading(DataDisplay));
// 使用示例
<EnhancedDataDisplay
isLoading={loading}
error={error}
data={data}
/>
6.2 渲染属性(Render Props)- React
jsx
class MouseTracker extends React.Component {
state = { x: 0, y: 0 };
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
};
render() {
return (
<div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}
// 使用
<MouseTracker render={({ x, y }) => (
<h1>The mouse position is ({x}, {y})</h1>
)} />
6.3 提供者模式(Provider Pattern)
javascript
// React Context
const ThemeContext = React.createContext();
class ThemeProvider extends React.Component {
state = { theme: 'light' };
toggleTheme = () => {
this.setState(prev => ({
theme: prev.theme === 'light' ? 'dark' : 'light'
}));
};
render() {
return (
<ThemeContext.Provider value={{
theme: this.state.theme,
toggleTheme: this.toggleTheme
}}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
// 消费
const ThemedButton = () => (
<ThemeContext.Consumer>
{({ theme, toggleTheme }) => (
<button
style={{
backgroundColor: theme === 'dark' ? '#333' : '#fff',
color: theme === 'dark' ? '#fff' : '#333'
}}
onClick={toggleTheme}
>
Toggle Theme
</button>
)}
</ThemeContext.Consumer>
);
6.4 Vue组合式函数(Composables)
javascript
// useMouse.js - Vue 3 Composition API
import { ref, onMounted, onUnmounted } from 'vue';
export function useMouse() {
const x = ref(0);
const y = ref(0);
const update = event => {
x.value = event.pageX;
y.value = event.pageY;
};
onMounted(() => window.addEventListener('mousemove', update));
onUnmounted(() => window.removeEventListener('mousemove', update));
return { x, y };
}
// useFetch.js
import { ref } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(false);
const fetchData = async () => {
loading.value = true;
try {
const response = await fetch(url);
data.value = await response.json();
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
};
fetchData();
return { data, error, loading, refetch: fetchData };
}
七、设计模式选择指南
| 模式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 工厂模式 | 需要创建多种类似对象 | 封装创建逻辑,易于扩展 | 增加系统复杂度 |
| 单例模式 | 全局唯一实例(配置、日志) | 节省内存,全局访问 | 测试困难,全局状态污染 |
| 观察者模式 | 一对多依赖关系 | 松耦合,易于扩展 | 可能引起内存泄漏 |
| 装饰器模式 | 动态添加功能 | 灵活,符合开放封闭原则 | 多层装饰复杂 |
| 策略模式 | 多种算法切换 | 避免条件语句,易于扩展 | 增加策略类数量 |
| 中间件模式 | 处理请求管道 | 关注点分离,易于测试 | 可能影响性能 |
八、最佳实践
- 不要过度设计:简单的代码比复杂的设计模式更好
- 模式组合使用:实际项目中经常组合多种模式
- 考虑可测试性:设计模式应提高代码的可测试性
- 保持一致性:团队内统一使用某些模式
- 文档化:对使用的设计模式进行文档说明
九、现代JavaScript中的新特性
9.1 Proxy和Reflect实现模式
javascript
// 使用Proxy实现数据绑定
function createObservable(obj, callback) {
return new Proxy(obj, {
set(target, property, value) {
const oldValue = target[property];
target[property] = value;
callback(property, oldValue, value);
return true;
},
get(target, property) {
console.log(`Getting ${property}`);
return target[property];
}
});
}
const user = createObservable(
{ name: 'John', age: 30 },
(prop, oldVal, newVal) => {
console.log(`${prop} changed from ${oldVal} to ${newVal}`);
}
);
user.name = 'Jane'; // 触发回调
9.2 使用ES6+特性简化模式
javascript
// 使用Symbol实现私有属性
const _private = Symbol('private');
class MyClass {
constructor() {
this[_private] = 'secret';
}
getSecret() {
return this[_private];
}
}
// 使用Generator实现迭代器模式
function* paginate(items, pageSize) {
for (let i = 0; i < items.length; i += pageSize) {
yield items.slice(i, i + pageSize);
}
}
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const page of paginate(items, 3)) {
console.log('Page:', page);
}
设计模式是解决常见问题的工具箱,理解它们有助于编写更优雅、可维护的代码。