什么是设计模式
做菜要有菜谱,游戏要有攻略,每个领域都存在一些能够让我们又好又快地达成目标的“套路”。在程序世界,编程的“套路”就是设计模式
设计模式是一套被反复使用的、经过验证的、用于解决软件设计中常见问题的通用解决方案。它们并不是具体的代码,而是对代码组织和架构的最佳实践的描述,旨在帮助开发者以一种更高效、更优雅的方式构建软件。
为什么要使用设计模式
- 设计模式提供了一种标准化的解决方案,使得开发者可以复用这些解决方案来解决类似的问题。
- 通过使用设计模式,开发者可以减少开发时间并避免陷入常见的陷阱或错误。
- 设计模式有助于构建结构清晰、易于理解和维护的代码。
开发者对设计模式的掌握程度,一定程度上反映着他用健壮的代码去解决具体的问题的能力。
设计模式分类
设计模式基于它们解决问题的核心关注点和目的分为三类:创建型模式、结构型模式和行为型模式。分别专注于对象的创建过程、对象之间的组合与关系以及对象之间的交互与责任分配。
创建型模式
创建型模式用于解决与对象创建情况相关的常见问题。
单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点。实现的方法就是先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
this.data = {};
}
getData() {
return this.data;
}
setData(key, value) {
this.data[key] = value;
}
}
const instance1 = new Singleton();
instance1.setData('name', '这是单例模式');
const instance2 = new Singleton();
console.log(instance2.getData()); // { name: '这是单例模式' }
console.log(instance1 === instance2); // true 即同一个实例
工厂模式
工厂模式定义了一个创建对象的接口,允许子类决定实例化哪一个类。
class Animal {
speak() {
throw new Error('方法必须被实现');
}
}
class Dog extends Animal {
speak() {
return '汪汪!';
}
}
class Cat extends Animal {
speak() {
return '喵喵!';
}
}
// 实现工厂方法
class AnimalFactory {
createAnimal() {
return new Error("未实现")
}
}
class ConcreteFactoryDog extends AnimalFactory {
createAnimal(){
return new Dog();
}
}
class ConcreteFactoryCat extends AnimalFactory {
createAnimal(){
return new Cat();
}
}
const dog = new ConcreteFactoryDog()
console.log(dog.createAnimal().speak()); // 汪汪!
const cat = new ConcreteFactoryCat()
console.log(cat.createAnimal().speak()); // 喵喵!
抽象工厂模式
抽象工厂和工厂模式的区别在于,工厂模式只生产一大类对象,而抽象工厂可以生产好几大类对象,就是所谓1
和n
的区别。抽象工厂模式存在灵活性差的问题,变更时会违反开比原则。
// 创建一组主题对象类型的抽象类
class AnimalFood {
provide() {
throw new Error('未实现');
}
}
class AnimalToy {
provide() {
throw new Error('未实现');
}
}
// 创建一组具体代表家族的对象
class HighQualityDogFood extends AnimalFood {
provide() {
return '高品质狗粮';
}
}
class HighQualityDogToy extends AnimalToy {
provide() {
return '高品质狗玩偶';
}
}
class CheapCatFood extends AnimalFood {
provide() {
return '便宜猫粮';
}
}
class CheapCatToy extends AnimalToy {
provide() {
return '便宜猫玩偶';
}
}
// 创建一个抽象工厂
class AnimalProductsAbstractFactory {
createFood() {
throw new Error('未实现');
}
createToy() {
throw new Error('未实现');
}
}
// 创建具体工厂类
class HighQualityAnimalProductsFactory extends AnimalProductsAbstractFactory {
createFood() {
return new HighQualityDogFood();
}
createToy() {
return new HighQualityDogToy();
}
}
class CheapAnimalProductsFactory extends AnimalProductsAbstractFactory {
createFood() {
return new CheapCatFood();
}
createToy() {
return new CheapCatToy();
}
}
// 使用具体工厂类来创建相关的对象
const highQualityAnimalProductsFactory = new HighQualityAnimalProductsFactory();
console.log(highQualityAnimalProductsFactory.createFood().provide()); // 高品质狗粮
console.log(highQualityAnimalProductsFactory.createToy().provide()); // 高品质狗玩偶
const cheapAnimalProductsFactory = new CheapAnimalProductsFactory();
console.log(cheapAnimalProductsFactory.createFood().provide()); // 便宜猫粮
console.log(cheapAnimalProductsFactory.createToy().provide()); // 便宜猫玩偶
原型模式
通过复制现有的对象来创建新对象,而不是通过实例化类。当对象的创建过程复杂或开销较大时用的比较多。
// 原型接口
class Prototype {
clone() {
throw new Error("未实现");
}
}
// 具体原型
class ConcretePrototype extends Prototype {
constructor(value) {
super();
this.value = value;
}
clone() {
return new ConcretePrototype(this.value);
}
}
const original = new ConcretePrototype('原始值');
const clone = original.clone();
console.log(original.value); // 原始值
console.log(clone.value); // 原始值
clone.value = '克隆值';
console.log(original.value); // 原始值
console.log(clone.value); // 克隆值
结构型模式
关注对象之间的组合,通过继承或接口的方式来实现不同对象之间的协作。
适配器模式
适配器通过将目标接口与现有接口适配,使得客户端可以使用不兼容的接口。
// 目标接口
class Target {
request() {
console.log('Target: 请求已被调用');
}
}
// 需要适配的类
class Adaptee {
specificRequest() {
console.log('Adaptee 方法已被访问');
}
}
// 适配器类,将 Adaptee 转换为 Target
class Adapter extends Target {
constructor(adaptee) {
super();
this.adaptee = adaptee;
}
request() {
this.adaptee.specificRequest();
}
}
// 使用适配器将客户端与 Adaptee 解耦
const client = new Adapter(new Adaptee());
client.request(); // Adaptee 方法已被访问
装饰者模式
允许在不改变对象自身的情况下,动态地为其添加新功能。
// 抽象组件类
class Component {
operation() {
throw new Error("未实现");
}
}
// 具体组件类
class ConcreteComponent extends Component {
operation() {
return 'ConcreteComponent:具体操作'
}
}
// 抽象装饰器类
class Decorator extends Component {
constructor(component) {
super();
this.component = component;
}
operation() {
this.component.operation();
}
}
// 具体装饰器类
class ConcreteDecoratorA extends Decorator {
operation() {
super.operation();
return 'ConcreteDecoratorA:添加操作'
}
}
class ConcreteDecoratorB extends Decorator {
operation() {
super.operation();
return 'ConcreteDecoratorB:添加操作'
}
}
// 使用装饰器组合对象
const component = new ConcreteComponent();
console.log(component.operation()); // ConcreteComponent:具体操作
const decoratorA = new ConcreteDecoratorA(component);
console.log(decoratorA.operation()); // ConcreteDecoratorA:添加操作
const decoratorB = new ConcreteDecoratorB(decoratorA);
console.log(decoratorB.operation()); // ConcreteDecoratorB:添加操作
代理模式
通过为一个对象提供一个代理来控制对该对象的访问。
// 主题接口
class Subject {
request() {
throw new Error("未实现");
}
}
// 真实主题
class RealSubject extends Subject {
request() {
return 'RealSubject: 发送请求';
}
}
// 代理类
class Proxy extends Subject {
constructor(realSubject) {
super();
this.realSubject = realSubject;
}
request() {
// 可以添加额外的功能
console.log('Proxy: 在真实请求前记录');
return this.realSubject.request();
}
}
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);
console.log(proxy.request()); // Proxy: 在真实请求前记录
// RealSubject: 发送请求
行为型模式
关注对象之间的责任分配和行为互动,描述类或对象之间如何进行通信。
观察者模式
用于建立一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。
// 被观察者
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notifyObservers(data) {
this.observers.forEach(observer => observer.update(data));
}
}
// 观察者接口
class Observer {
update(data) {
throw new Error("未实现");
}
}
// 具体观察者
class ConcreteObserverA extends Observer {
update(data) {
console.log(`ConcreteObserverA: 对${data}做出响应`);
}
}
class ConcreteObserverB extends Observer {
update(data) {
console.log(`ConcreteObserverB: 对${data}做出响应`);
}
}
const subject = new Subject();
const observerA = new ConcreteObserverA();
const observerB = new ConcreteObserverB();
subject.addObserver(observerA);
subject.addObserver(observerB);
subject.notifyObservers('事件1'); // ConcreteObserverA: 对事件1做出响应
// ConcreteObserverB: 对事件1做出响应
subject.removeObserver(observerA);
subject.notifyObservers('事件2'); // 输出: ConcreteObserverB: 对事件2做出响应
参考
- 掘金小册 - JavaScript 设计模式核心原理与应用实践
- JavaScript设计模式:让你的代码像个天才!你是否曾经在JavaScript代码中迷失过? 是否曾经感到自己的代码 - 掘金 (juejin.cn)
总结
设计模式帮助开发者避免重复造轮子,构建更健壮、可扩展和易于维护的软件系统。如今同样已经成为前端面试中无法回避、同时具有较高候选人区分度的一个核心考点。学好设计模式对面试、工作都有很大的帮助,一起加油!
最后
以上就是JS中常见的设计模式介绍,如果需要补充,欢迎评论!
码字不易,感谢三连!
已将学习代码上传至 github,欢迎大家学习指正!
技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 “点赞 收藏+关注” ,感谢支持!!