设计模式实现
设计模式是软件开发中解决常见问题的可复用方案。在JavaScript中,设计模式能够帮助开发者构建更灵活、可维护的代码结构。下面将探讨几种常见的设计模式及其实现方式。
单例模式
单例模式确保一个类只有一个实例,并提供全局访问点。在JavaScript中,可以通过闭包或模块化实现单例。
const Singleton = (function() {
let instance;
function createInstance() {
return {
name: 'Singleton Instance',
log: function() {
console.log(this.name);
}
};
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
观察者模式
观察者模式定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。
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(`Received data: ${data}`);
}
}
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.notify('Hello Observers!');
工厂模式
工厂模式提供创建对象的接口,让子类决定实例化哪个类。在JavaScript中,可以使用函数或类实现工厂模式。
class Car {
constructor(options) {
this.type = options.type || 'sedan';
this.color = options.color || 'white';
}
}
class Truck {
constructor(options) {
this.type = options.type || 'truck';
this.color = options.color || 'black';
}
}
class VehicleFactory {
createVehicle(options) {
switch(options.vehicleType) {
case 'car':
return new Car(options);
case 'truck':
return new Truck(options);
default:
throw new Error('Invalid vehicle type');
}
}
}
const factory = new VehicleFactory();
const myCar = factory.createVehicle({
vehicleType: 'car',
color: 'red'
});
策略模式
策略模式定义一系列算法,封装每个算法,并使它们可以互换。这种模式让算法的变化独立于使用它的客户端。
const strategies = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
class Calculator {
constructor(strategy) {
this.strategy = strategy;
}
execute(a, b) {
return strategies[this.strategy](a, b);
}
}
const calc = new Calculator('add');
console.log(calc.execute(5, 3)); // 8
装饰器模式
装饰器模式动态地给对象添加额外的职责,相比继承更加灵活。在JavaScript中,可以通过高阶函数或ES7装饰器语法实现。
function withLogging(fn) {
return function(...args) {
console.log(`Calling function with args: ${args}`);
const result = fn.apply(this, args);
console.log(`Function returned: ${result}`);
return result;
};
}
function add(a, b) {
return a + b;
}
const loggedAdd = withLogging(add);
loggedAdd(2, 3);
适配器模式
适配器模式将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以一起工作。
class OldCalculator {
operations(a, b, operation) {
switch(operation) {
case 'add':
return a + b;
case 'sub':
return a - b;
default:
return NaN;
}
}
}
class NewCalculator {
add(a, b) {
return a + b;
}
subtract(a, b) {
return a - b;
}
}
class CalculatorAdapter {
constructor() {
this.calculator = new NewCalculator();
}
operations(a, b, operation) {
switch(operation) {
case 'add':
return this.calculator.add(a, b);
case 'sub':
return this.calculator.subtract(a, b);
default:
return NaN;
}
}
}
const oldCalc = new OldCalculator();
console.log(oldCalc.operations(5, 3, 'add'));
const adapter = new CalculatorAdapter();
console.log(adapter.operations(5, 3, 'add'));
代理模式
代理模式为其他对象提供一种代理以控制对这个对象的访问。在JavaScript中,Proxy对象原生支持这种模式。
const person = {
name: 'John',
age: 30
};
const personProxy = new Proxy(person, {
get(target, property) {
console.log(`Getting ${property}`);
return target[property];
},
set(target, property, value) {
console.log(`Setting ${property} to ${value}`);
target[property] = value;
return true;
}
});
console.log(personProxy.name);
personProxy.age = 31;
状态模式
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
class TrafficLight {
constructor() {
this.states = {
red: new RedLight(this),
yellow: new YellowLight(this),
green: new GreenLight(this)
};
this.currentState = this.states.red;
}
change(state) {
this.currentState = this.states[state];
}
show() {
this.currentState.show();
}
}
class LightState {
constructor(light) {
this.light = light;
}
}
class RedLight extends LightState {
show() {
console.log('Red Light - Stop');
setTimeout(() => {
this.light.change('green');
}, 3000);
}
}
class GreenLight extends LightState {
show() {
console.log('Green Light - Go');
setTimeout(() => {
this.light.change('yellow');
}, 3000);
}
}
class YellowLight extends LightState {
show() {
console.log('Yellow Light - Wait');
setTimeout(() => {
this.light.change('red');
}, 1000);
}
}
const trafficLight = new TrafficLight();
trafficLight.show();
组合模式
组合模式将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
class Component {
constructor(name) {
this.name = name;
}
add(component) {
throw new Error('Not implemented');
}
remove(component) {
throw new Error('Not implemented');
}
display(depth) {
throw new Error('Not implemented');
}
}
class Leaf extends Component {
constructor(name) {
super(name);
}
display(depth) {
console.log('-'.repeat(depth) + this.name);
}
}
class Composite extends Component {
constructor(name) {
super(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);
}
}
display(depth) {
console.log('-'.repeat(depth) + this.name);
this.children.forEach(child => {
child.display(depth + 2);
});
}
}
const root = new Composite('Root');
const branch1 = new Composite('Branch 1');
const branch2 = new Composite('Branch 2');
const leaf1 = new Leaf('Leaf 1');
const leaf2 = new Leaf('Leaf 2');
root.add(branch1);
root.add(branch2);
branch1.add(leaf1);
branch2.add(leaf2);
root.display(0);
命令模式
命令模式将请求封装为对象,从而允许使用不同的请求、队列或日志来参数化其他对象,并支持可撤销的操作。
class Calculator {
constructor() {
this.currentValue = 0;
this.history = [];
}
executeCommand(command) {
this.currentValue = command.execute(this.currentValue);
this.history.push(command);
}
undo() {
const command = this.history.pop();
if (command) {
this.currentValue = command.undo(this.currentValue);
}
}
}
class AddCommand {
constructor(value) {
this.value = value;
}
execute(currentValue) {
return currentValue + this.value;
}
undo(currentValue) {
return currentValue - this.value;
}
}
class SubtractCommand {
constructor(value) {
this.value = value;
}
execute(currentValue) {
return currentValue - this.value;
}
undo(currentValue) {
return currentValue + this.value;
}
}
const calculator = new Calculator();
calculator.executeCommand(new AddCommand(10));
calculator.executeCommand(new SubtractCommand(5));
console.log(calculator.currentValue); // 5
calculator.undo();
console.log(calculator.currentValue); // 10
模板方法模式
模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构的情况下重定义该算法的某些特定步骤。
class DataProcessor {
process() {
this.loadData();
this.validateData();
this.analyzeData();
this.reportResults();
}
loadData() {
throw new Error('loadData must be implemented');
}
validateData() {
console.log('Default validation');
}
analyzeData() {
throw new Error('analyzeData must be implemented');
}
reportResults() {
console.log('Default reporting');
}
}
class CSVProcessor extends DataProcessor {
loadData() {
console.log('Loading CSV data');
}
analyzeData() {
console.log('Analyzing CSV data');
}
}
class JSONProcessor extends DataProcessor {
loadData() {
console.log('Loading JSON data');
}
analyzeData() {
console.log('Analyzing JSON data');
}
reportResults() {
console.log('Generating JSON report');
}
}
const csvProcessor = new CSVProcessor();
csvProcessor.process();
const jsonProcessor = new JSONProcessor();
jsonProcessor.process();
迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
class Iterator {
constructor(items) {
this.index = 0;
this.items = items;
}
next() {
return this.items[this.index++];
}
hasNext() {
return this.index < this.items.length;
}
}
class Collection {
constructor() {
this.items = [];
}
addItem(item) {
this.items.push(item);
}
getIterator() {
return new Iterator(this.items);
}
}
const collection = new Collection();
collection.addItem('Item 1');
collection.addItem('Item 2');
collection.addItem('Item 3');
const iterator = collection.getIterator();
while(iterator.hasNext()) {
console.log(iterator.next());
}
中介者模式
中介者模式用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
class ChatRoom {
showMessage(user, message) {
const time = new Date();
const sender = user.getName();
console.log(`${time} [${sender}]: ${message}`);
}
}
class User {
constructor(name, chatMediator) {
this.name = name;
this.chatMediator = chatMediator;
}
getName() {
return this.name;
}
send(message) {
this.chatMediator.showMessage(this, message);
}
}
const chatRoom = new ChatRoom();
const user1 = new User('John', chatRoom);
const user2 = new User('Jane', chatRoom);
user1.send('Hi there!');
user2.send('Hey!');
备忘录模式
备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复对象到原先保存的状态。
class EditorMemento {
constructor(content) {
this.content = content;
}
getContent() {
return this.content;
}
}
class Editor {
constructor() {
this.content = '';
this.history = [];
this.currentState = -1;
}
type(text) {
this.content += text;
}
save() {
const memento = new EditorMemento(this.content);
this.history.push(memento);
this.currentState = this.history.length - 1;
return memento;
}
restore(memento) {
if (memento) {
this.content = memento.getContent();
}
}
undo() {
if (this.currentState > 0) {
this.currentState--;
this.content = this.history[this.currentState].getContent();
}
}
redo() {
if (this.currentState < this.history.length - 1) {
this.currentState++;
this.content = this.history[this.currentState].getContent();
}
}
}
const editor = new Editor();
editor.type('First line\n');
editor.save();
editor.type('Second line\n');
editor.save();
editor.type('Third line\n');
console.log(editor.content);
editor.undo();
console.log(editor.content);
editor.redo();
console.log(editor.content);
访问者模式
访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
class Employee {
constructor(name, salary) {
this.name = name;
this.salary = salary;
}
accept(visitor) {
visitor.visit(this);
}
}
class Department {
constructor() {
this.employees = [];
}
addEmployee(employee) {
this.employees.push(employee);
}
accept(visitor) {
this.employees.forEach(employee => {
employee.accept(visitor);
});
}
}
class SalaryVisitor {
visit(employee) {
employee.salary = Math.floor(employee.salary * 1.1);
console.log(`${employee.name}'s new salary: ${employee.salary}`);
}
}
class NameVisitor {
visit(employee) {
console.log(`Employee name: ${employee.name}`);
}
}
const dept = new Department();
dept.addEmployee(new Employee('John', 50000));
dept.addEmployee(new Employee('Jane', 60000));
const salaryVisitor = new SalaryVisitor();
dept.accept(salaryVisitor);
const nameVisitor = new NameVisitor();
dept.accept(nameVisitor);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn