设计模式的历史与发展
引言
设计模式的概念并非凭空产生,它有着深厚的历史背景和演进过程。从建筑领域的模式语言到软件工程中的经典著作,再到现代前端开发中的广泛应用,设计模式经历了丰富的发展历程。
了解设计模式的历史有助于我们更好地理解它们的本质和价值,也能帮助我们在现代开发中更恰当地应用这些模式。
GoF(Gang of Four)经典设计模式的起源与演变
模式概念的起源
设计模式的概念最早可以追溯到建筑领域。1977年,建筑师Christopher Alexander在他的著作《建筑模式语言》(A Pattern Language)中首次提出了"模式"的概念。他将模式定义为"在特定环境中解决特定问题的经过验证的解决方案"。
Alexander认为,模式不仅仅是解决问题的方法,更是一种可以重复使用的、经过验证的设计思想。这一思想后来被软件工程领域借鉴和发扬。
GoF的贡献
1994年,Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides(被称为"四人组"或GoF)出版了《设计模式:可复用面向对象软件的基础》一书,正式提出了23种设计模式。这四位作者都是面向对象编程领域的专家,他们在C++和Smalltalk等语言的实践中总结出了这些模式。
这本书成为了软件工程领域的经典著作,对软件设计产生了深远影响。
23种经典设计模式
GoF将这23种设计模式分为三类:
创建型模式(5种)
- Abstract Factory(抽象工厂) - 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
- Builder(建造者) - 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- Factory Method(工厂方法) - 定义一个用于创建对象的接口,让子类决定实例化哪一个类
- Prototype(原型) - 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
- Singleton(单例) - 保证一个类仅有一个实例,并提供一个访问它的全局访问点
结构型模式(7种)
- Adapter(适配器) - 将一个类的接口转换成客户希望的另外一个接口
- Bridge(桥接) - 将抽象部分与它的实现部分分离,使它们都可以独立地变化
- Composite(组合) - 将对象组合成树形结构以表示"部分-整体"的层次结构
- Decorator(装饰) - 动态地给一个对象添加一些额外的职责
- Facade(外观) - 为子系统中的一组接口提供一个一致的界面
- Flyweight(享元) - 运用共享技术有效地支持大量细粒度的对象
- Proxy(代理) - 为其他对象提供一个代理以控制对这个对象的访问
行为型模式(11种)
- Chain of Responsibility(责任链) - 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系
- Command(命令) - 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化
- Interpreter(解释器) - 给定一个语言,定义它的文法的一种表示,并定义一个解释器
- Iterator(迭代器) - 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示
- Mediator(中介者) - 用一个中介对象来封装一系列的对象交互
- Memento(备忘录) - 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
- Observer(观察者) - 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- State(状态) - 允许一个对象在其内部状态改变时改变它的行为
- Strategy(策略) - 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换
- Template Method(模板方法) - 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中
- Visitor(访问者) - 表示一个作用于某对象结构中的各元素的操作
GoF模式的影响
GoF的《设计模式》一书对软件工程领域产生了深远影响:
- 标准化了设计词汇 - 为开发者提供了通用的设计语言
- 提高了设计质量 - 提供了经过验证的解决方案
- 促进了代码复用 - 模式可以跨项目、跨团队复用
- 改善了团队沟通 - 统一的设计词汇便于交流
现代 JavaScript 中的设计模式实践
随着 JavaScript 和前端技术的发展,设计模式在现代开发中有了新的应用场景和实现方式。
JavaScript 特性对设计模式的影响
1. 函数是一等公民
JavaScript 中函数是一等公民,这使得许多设计模式有了更简洁的实现方式:
// 策略模式的传统实现
class SortStrategy {
sort(data) {
throw new Error('必须实现 sort 方法');
}
}
class QuickSort extends SortStrategy {
sort(data) {
console.log('快速排序');
return data.sort();
}
}
class MergeSort extends SortStrategy {
sort(data) {
console.log('归并排序');
return data.sort();
}
}
// 使用函数的简化实现
const quickSort = (data) => {
console.log('快速排序');
return data.sort();
};
const mergeSort = (data) => {
console.log('归并排序');
return data.sort();
};
// 策略选择
const sortStrategies = {
quick: quickSort,
merge: mergeSort
};
function sortData(data, strategy) {
return sortStrategies[strategy](data);
}2. 闭包和模块模式
JavaScript 的闭包特性使得我们可以轻松实现单例模式和模块模式:
// 模块模式实现配置管理器
const ConfigManager = (function() {
let instance;
let config = {};
function createInstance() {
return {
set(key, value) {
config[key] = value;
},
get(key) {
return config[key];
},
getAll() {
return { ...config };
}
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const config1 = ConfigManager.getInstance();
const config2 = ConfigManager.getInstance();
console.log(config1 === config2); // true3. ES6+ 特性支持
ES6 及以后版本提供了类、模块、箭头函数等特性,让设计模式实现更加优雅:
// 使用 ES6 类实现观察者模式
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
update(data) {
console.log('收到数据更新:', data);
}
}
// 使用示例
const subject = new Subject();
const observer = new Observer();
subject.subscribe(observer);
subject.notify('Hello World');现代框架中的设计模式
1. React 中的设计模式
React 框架中大量使用了设计模式:
// 高阶组件(HOC)- 装饰器模式的应用
function withAuth(WrappedComponent) {
return function AuthenticatedComponent(props) {
const isAuthenticated = useAuth(); // 假设的认证 hook
if (!isAuthenticated) {
return <div>请先登录</div>;
}
return <WrappedComponent {...props} />;
};
}
// 使用高阶组件
const ProtectedProfile = withAuth(ProfileComponent);
// Hook - 策略模式的应用
function useApi(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}2. Vue 中的设计模式
Vue 框架中也广泛应用了设计模式:
// Mixin - 策略模式的应用
const myMixin = {
created() {
this.hello();
},
methods: {
hello() {
console.log('Hello from mixin!');
}
}
};
// 组件中使用 mixin
Vue.component('my-component', {
mixins: [myMixin],
template: '<div>组件内容</div>'
});
// 插件 - 外观模式的应用
const MyPlugin = {
install(Vue, options) {
Vue.prototype.$myMethod = function() {
// 插件方法
};
Vue.directive('my-directive', {
// 自定义指令
});
}
};
Vue.use(MyPlugin);Node.js 生态中的设计模式
在 Node.js 后端开发中,设计模式也有广泛应用:
// 中间件模式 - 责任链模式的应用
const express = require('express');
const app = express();
// 中间件1
app.use((req, res, next) => {
console.log('中间件1');
next();
});
// 中间件2
app.use((req, res, next) => {
console.log('中间件2');
next();
});
// 路由处理器
app.get('/', (req, res) => {
res.send('Hello World');
});
// 事件驱动 - 观察者模式的应用
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('事件被触发');
});
myEmitter.emit('event');设计模式的发展趋势
1. 函数式编程与设计模式的融合
随着函数式编程的兴起,许多传统面向对象的设计模式有了函数式的实现方式:
// 函数式实现策略模式
const strategies = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
function calculate(operation, a, b) {
return strategies[operation](a, b);
}
console.log(calculate('add', 5, 3)); // 82. 响应式编程中的模式
响应式编程(如 RxJS)引入了新的模式和概念:
// Observable - 观察者模式的现代实现
import { Observable } from 'rxjs';
const observable = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
subscriber.next(3);
setTimeout(() => {
subscriber.next(4);
subscriber.complete();
}, 1000);
});
observable.subscribe({
next(x) { console.log('得到值 ' + x); },
error(err) { console.error('发生错误: ' + err); },
complete() { console.log('完成'); }
});3. 微服务架构中的模式
在微服务架构中,许多分布式系统模式变得重要:
// 断路器模式的简化实现
class CircuitBreaker {
constructor(request, threshold = 5, timeout = 60000) {
this.request = request;
this.threshold = threshold;
this.timeout = timeout;
this.failureCount = 0;
this.lastFailureTime = null;
this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
}
async call(...args) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.timeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('断路器开启,请求被拒绝');
}
}
try {
const result = await this.request(...args);
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.threshold) {
this.state = 'OPEN';
}
}
}总结
设计模式从建筑领域的概念发展到软件工程的经典著作,再到现代前端和后端开发的广泛应用,经历了丰富的演进过程。
- 历史传承 - GoF 的 23 种设计模式仍然是现代软件开发的基础
- 语言特性影响 - JavaScript 的函数式特性和现代语法为模式实现提供了新的可能性
- 框架集成 - React、Vue 等现代框架大量使用设计模式
- 发展趋势 - 函数式编程、响应式编程和微服务架构带来了新的模式和应用场景
理解设计模式的历史发展有助于我们在现代开发中更好地应用这些模式,同时也提醒我们不要为了使用模式而使用模式,应该根据实际需求选择合适的设计方案。
在接下来的章节中,我们将开始深入探讨创建型模式,学习如何优雅地创建对象。