在JavaScript中,有多种常见的设计模式可供使用。以下是13种常见的JavaScript设计模式:
JavaScript设计模式
- 单例模式(Singleton Pattern)
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 原型模式(Prototype Pattern)
- 建造者模式(Builder Pattern)
- 适配器模式(Adapter Pattern)
- 装饰器模式(Decorator Pattern)
- 观察者模式(Observer Pattern)
- 发布-订阅模式(Publish-Subscribe Pattern)
- 策略模式(Strategy Pattern)
- 状态模式(State Pattern)
- 代理模式(Proxy Pattern)
- 迭代器模式(Iterator Pattern)
简要说明
每种设计模式都有其独特的特点和用途,下面是对每种设计模式的简要说明:
-
单例模式 (Singleton Pattern):
单例模式用于限制一个类只有一个实例,并提供一个全局访问点。 -
工厂模式 (Factory Pattern):
工厂模式通过使用工厂方法创建对象,而不是直接调用构造函数来创建对象。 -
抽象工厂模式 (Abstract Factory Pattern):
抽象工厂模式提供了一种创建相关对象的接口,而无需指定具体类。 -
原型模式 (Prototype Pattern):
原型模式基于现有对象克隆创建新对象,避免了直接实例化。 -
建造者模式 (Builder Pattern):
建造者模式用于创建复杂对象,通过一步一步地构建对象来实现。 -
适配器模式 (Adapter Pattern):
适配器模式用于将不兼容的接口转换为可兼容的接口。 -
装饰器模式 (Decorator Pattern):
装饰器模式允许在不修改原始对象的情况下给对象添加新功能。 -
观察者模式 (Observer Pattern):
观察者模式定义了一种一对多的依赖关系,使得多个观察者对象可以同时监听一个主题对象。 -
发布-订阅模式 (Publish-Subscribe Pattern):
发布-订阅模式允许多个订阅者订阅特定事件,当事件发生时,发布者会通知所有订阅者。 -
策略模式 (Strategy Pattern):
策略模式定义了一系列可以互相替换的算法,并使得算法的选择与使用独立于客户端。 -
状态模式 (State Pattern):
状态模式允许对象在内部状态改变时改变其行为,使对象看起来似乎修改了其类。 -
代理模式 (Proxy Pattern):
代理模式提供了一个代理对象来控制对实际对象的访问,并可以通过代理对象添加额外的功能。 -
迭代器模式 (Iterator Pattern):
迭代器模式提供一种访问聚合对象元素的方法,而不需要暴露聚合对象的内部结构。
这些设计模式可以帮助您更好地组织和设计JavaScript代码,提高代码的可维护性和可扩展性。具体使用哪种设计模式取决于问题的性质和需求。
详细代码说明:
以下是对每种设计模式的详细代码说明:
- 单例模式 (Singleton Pattern):
var Singleton = (function () {var instance;function createInstance() {var object = new Object("I am the instance");return object;}return {getInstance: function () {if (!instance) {instance = createInstance();}return instance;},};
})();var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();console.log(instance1 === instance2); // Output: true
- 工厂模式 (Factory Pattern):
function ShapeFactory() {}ShapeFactory.prototype.createShape = function (type) {if (type === "circle") {return new Circle();} else if (type === "rectangle") {return new Rectangle();} else if (type === "triangle") {return new Triangle();}
};function Circle() {this.type = "circle";
}function Rectangle() {this.type = "rectangle";
}function Triangle() {this.type = "triangle";
}var factory = new ShapeFactory();
var circle = factory.createShape("circle");
var rectangle = factory.createShape("rectangle");
var triangle = factory.createShape("triangle");console.log(circle.type); // Output: circle
console.log(rectangle.type); // Output: rectangle
console.log(triangle.type); // Output: triangle
- 抽象工厂模式 (Abstract Factory Pattern):
function FurnitureFactory() {}FurnitureFactory.prototype.createChair = function () {throw new Error("This method should be overridden");
};FurnitureFactory.prototype.createTable = function () {throw new Error("This method should be overridden");
};function ModernFurnitureFactory() {}ModernFurnitureFactory.prototype = Object.create(FurnitureFactory.prototype);
ModernFurnitureFactory.prototype.constructor = ModernFurnitureFactory;ModernFurnitureFactory.prototype.createChair = function () {return new ModernChair();
};ModernFurnitureFactory.prototype.createTable = function () {return new ModernTable();
};function VictorianFurnitureFactory() {}VictorianFurnitureFactory.prototype = Object.create(FurnitureFactory.prototype);
VictorianFurnitureFactory.prototype.constructor = VictorianFurnitureFactory;VictorianFurnitureFactory.prototype.createChair = function () {return new VictorianChair();
};VictorianFurnitureFactory.prototype.createTable = function () {return new VictorianTable();
};function ModernChair() {this.type = "modern chair";
}function ModernTable() {this.type = "modern table";
}function VictorianChair() {this.type = "victorian chair";
}function VictorianTable() {this.type = "victorian table";
}var modernFactory = new ModernFurnitureFactory();
var modernChair = modernFactory.createChair();
var modernTable = modernFactory.createTable();var victorianFactory = new VictorianFurnitureFactory();
var victorianChair = victorianFactory.createChair();
var victorianTable = victorianFactory.createTable();console.log(modernChair.type); // Output: modern chair
console.log(modernTable.type); // Output: modern table
console.log(victorianChair.type); // Output: victorian chair
console.log(victorianTable.type); // Output: victorian table
- 原型模式 (Prototype Pattern):
function Shape() {}Shape.prototype.clone = function () {throw new Error("This method should be overridden");
};function Circle(radius) {this.radius = radius;
}Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;Circle.prototype.clone = function () {return new Circle(this.radius);
};var circle = new Circle(5);
var clonedCircle = circle.clone();console.log(clonedCircle.radius); // Output: 5
- 建造者模式 (Builder Pattern):
function Car() {this.color = "";this.model = "";this.engine = "";
}function CarBuilder() {this.car = new Car();
}CarBuilder.prototype.setColor = function (color) {this.car.color = color;return this;
};CarBuilder.prototype.setModel = function (model) {this.car.model = model;return this;
};CarBuilder.prototype.setEngine = function (engine) {this.car.engine = engine;return this;
};CarBuilder.prototype.build = function () {return this.car;
};var car = new CarBuilder().setColor("red").setModel("sedan").setEngine("V8").build();console.log(car.color); // Output: red
console.log(car.model); // Output: sedan
console.log(car.engine); // Output: V8
- 适配器模式 (Adapter Pattern):
function MediaPlayer() {}MediaPlayer.prototype.play = function (audioType, fileName) {throw new Error("This method should be overridden");
};function AudioPlayer() {}AudioPlayer.prototype = Object.create(MediaPlayer.prototype);
AudioPlayer.prototype.constructor = AudioPlayer;AudioPlayer.prototype.play = function (audioType, fileName) {if (audioType === "mp3") {console.log("Playing mp3 file: " + fileName);} else {throw new Error("Unsupported audio type: " + audioType);}
};function MediaAdapter(audioType) {if (audioType === "mp3") {this.audioPlayer = new AudioPlayer();}
}MediaAdapter.prototype.play = function (audioType, fileName) {if (audioType === "mp3") {this.audioPlayer.play(audioType, fileName);} else {throw new Error("Unsupported audio type: " + audioType);}
};function AudioPlayerAdapter() {}AudioPlayerAdapter.prototype = Object.create(MediaPlayer.prototype);
AudioPlayerAdapter.prototype.constructor = AudioPlayerAdapter;AudioPlayerAdapter.prototype.play = function (audioType, fileName) {if (audioType === "mp3") {var mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);} else {throw new Error("Unsupported audio type: " + audioType);}
};var audioPlayer = new AudioPlayerAdapter();
audioPlayer.play("mp3", "song.mp3"); // Output: Playing mp3 file: song.mp3
- 装饰器模式 (Decorator Pattern):
function Pizza() {}Pizza.prototype.getDescription = function () {throw new Error("This method should be overridden");
};Pizza.prototype.cost = function () {throw new Error("This method should be overridden");
};function MargheritaPizza() {}MargheritaPizza.prototype = Object.create(Pizza.prototype);
MargheritaPizza.prototype.constructor = MargheritaPizza;MargheritaPizza.prototype.getDescription = function () {return "Margherita Pizza";
};MargheritaPizza.prototype.cost = function () {return 10;
};function PizzaDecorator(pizza) {this.pizza = pizza;
}PizzaDecorator.prototype.getDescription = function () {return this.pizza.getDescription();
};PizzaDecorator.prototype.cost = function () {return this.pizza.cost();
};function ExtraCheeseDecorator(pizza) {PizzaDecorator.call(this, pizza);
}ExtraCheeseDecorator.prototype = Object.create(PizzaDecorator.prototype);
ExtraCheeseDecorator.prototype.constructor = ExtraCheeseDecorator;ExtraCheeseDecorator.prototype.getDescription = function () {return this.pizza.getDescription() + ", Extra Cheese";
};ExtraCheeseDecorator.prototype.cost = function () {return this.pizza.cost() + 2;
};var margheritaPizza = new MargheritaPizza();
var extraCheesePizza = new ExtraCheeseDecorator(margheritaPizza);console.log(extraCheesePizza.getDescription()); // Output: Margherita Pizza, Extra Cheese
console.log(extraCheesePizza.cost()); // Output: 12
- 观察者模式 (Observer Pattern):
function Subject() {this.observers = [];
}Subject.prototype.subscribe = function (observer) {this.observers.push(observer);
};Subject.prototype.unsubscribe = function (observer) {var index = this.observers.indexOf(observer);if (index !== -1) {this.observers.splice(index, 1);}
};Subject.prototype.notify = function () {for (var i = 0; i < this.observers.length; i++) {this.observers[i].update();}
};function Observer(name) {this.name = name;
}Observer.prototype.update = function () {console.log(this.name + " received an update");
};var subject = new Subject();var observer1 = new Observer("Observer 1");
var observer2 = new Observer("Observer 2");
var observer3 = new Observer("Observer 3");subject.subscribe(observer1);
subject.subscribe(observer2);
subject.subscribe(observer3);subject.notify();
// Output: Observer 1 received an update
// Output: Observer 2 received an update
// Output: Observer 3 received an update
- 发布-订阅模式 (Publish-Subscribe Pattern):
function PubSub() {this.subscribers = {};
}PubSub.prototype.subscribe = function (event, callback) {if (!this.subscribers[event]) {this.subscribers[event] = [];}this.subscribers[event].push(callback);
};PubSub.prototype.unsubscribe = function (event,callback) {if (this.subscribers[event]) {var index = this.subscribers[event].indexOf(callback);if (index !== -1) {this.subscribers[event].splice(index, 1);}}
};PubSub.prototype.publish = function (event, data) {if (this.subscribers[event]) {this.subscribers[event].forEach(function (callback) {callback(data);});}
};var pubSub = new PubSub();var callback1 = function (data) {console.log("Callback 1 received data: " + data);
};var callback2 = function (data) {console.log("Callback 2 received data: " + data);
};pubSub.subscribe("event1", callback1);
pubSub.subscribe("event1", callback2);pubSub.publish("event1", "Hello World");
// Output: Callback 1 received data: Hello World
// Output: Callback 2 received data: Hello WorldpubSub.unsubscribe("event1", callback2);pubSub.publish("event1", "Hello Again");
// Output: Callback 1 received data: Hello Again10. 状态模式 (State Pattern):```javascript
function TrafficLight() {this.currentState = new RedLightState(this);
}TrafficLight.prototype.changeState = function (state) {this.currentState = state;
};TrafficLight.prototype.start = function () {this.currentState.start();
};function RedLightState(trafficLight) {this.trafficLight = trafficLight;
}RedLightState.prototype.start = function () {console.log("Red Light - Stop");this.trafficLight.changeState(new GreenLightState(this.trafficLight));
};function GreenLightState(trafficLight) {this.trafficLight = trafficLight;
}GreenLightState.prototype.start = function () {console.log("Green Light - Go");this.trafficLight.changeState(new YellowLightState(this.trafficLight));
};function YellowLightState(trafficLight) {this.trafficLight = trafficLight;
}YellowLightState.prototype.start = function () {console.log("Yellow Light - Prepare to Stop");this.trafficLight.changeState(new RedLightState(this.trafficLight));
};var trafficLight = new TrafficLight();trafficLight.start();
// Output: Red Light - StoptrafficLight.start();
// Output: Green Light - GotrafficLight.start();
// Output: Yellow Light - Prepare to StoptrafficLight.start();
// Output: Red Light - Stop
- 空对象模式 (Null Object Pattern):
function Animal(name) {this.name = name;
}Animal.prototype.makeSound = function () {throw new Error("This method should be overridden");
};function Dog(name) {Animal.call(this, name);
}Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;Dog.prototype.makeSound = function () {console.log(this.name + " barks");
};function NullAnimal() {}NullAnimal.prototype.makeSound = function () {console.log("No sound");
};function AnimalFactory() {}AnimalFactory.prototype.createAnimal = function (name) {if (name === "dog") {return new Dog(name);} else {return new NullAnimal();}
};var animalFactory = new AnimalFactory();var animal1 = animalFactory.createAnimal("dog");
animal1.makeSound(); // Output: dog barksvar animal2 = animalFactory.createAnimal("cat");
animal2.makeSound(); // Output: No sound
- 模板方法模式 (Template Method Pattern):
function Beverage() {}Beverage.prototype.prepare = function () {this.boilWater();this.brew();this.pourInCup();this.addCondiments();
};Beverage.prototype.boilWater = function () {console.log("Boiling water");
};Beverage.prototype.pourInCup = function () {console.log("Pouring into cup");
};Beverage.prototype.brew = function () {throw new Error("This method should be overridden");
};Beverage.prototype.addCondiments = function () {throw new Error("This method should be overridden");
};function Coffee() {}Coffee.prototype = Object.create(Beverage.prototype);
Coffee.prototype.constructor = Coffee;Coffee.prototype.brew = function () {console.log("Brewing coffee");
};Coffee.prototype.addCondiments = function () {console.log("Adding sugar and milk");
};function Tea() {}Tea.prototype = Object.create(Beverage.prototype);
Tea.prototype.constructor = Tea;Tea.prototype.brew = function () {console.log("Steeping tea");
};Tea.prototype.addCondiments = function () {console.log("Adding lemon");
};var coffee = new Coffee();
coffee.prepare();
// Output:
// Boiling water
// Brewing coffee
// Pouring into cup
// Adding sugar and milkvar tea = new Tea();
tea.prepare();
// Output:
// Boiling water
// Steeping tea
// Pouring into cup
// Adding lemon
这是一些常见的设计模式的例子