在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 World
pubSub.unsubscribe("event1", callback2);
pubSub.publish("event1", "Hello Again");
// Output: Callback 1 received data: Hello Again
10. 状态模式 (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 - Stop
trafficLight.start();
// Output: Green Light - Go
trafficLight.start();
// Output: Yellow Light - Prepare to Stop
trafficLight.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 barks
var 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 milk
var tea = new Tea();
tea.prepare();
// Output:
// Boiling water
// Steeping tea
// Pouring into cup
// Adding lemon
这是一些常见的设计模式的例子