主题
设计模式
原型模式
作用: 公共方法存放在原型。 好处: 在原型添加新方法,现有实例即时生效; 内存节省。
js
// 定义敌人原型
function Enemy(type) {
this.type = type;
}
// 共享攻击方法(所有敌人都会)
Enemy.prototype.attack = function () {
console.log(`${this.type}发起攻击!`);
};
// 创建实例
const dragon = new Enemy('火龙');
const goblin = new Enemy('哥布林');
dragon.attack(); // 火龙发起攻击!
goblin.attack(); // 哥布林发起攻击!
// 验证方法共享
console.log(dragon.attack === goblin.attack);工厂模式
作用: 根据不同的需求创建不同类型的对象,不需要去 new 直接获取实例
js
// 定义一个基类 Animal
class Animal {
speak() {
return this.makeSound();
}
}
// 定义具体的 Dog 类
class Dog extends Animal {
makeSound() {
return 'Woof'; // 狗的叫声
}
}
// 定义具体的 Cat 类
class Cat extends Animal {
makeSound() {
return 'Meow'; // 猫的叫声
}
}
// 工厂类,负责创建不同类型的动物对象
class AnimalFactory {
createAnimal(type) {
switch (type) {
case 'dog':
return new Dog(); // 创建 Dog 实例
case 'cat':
return new Cat(); // 创建 Cat 实例
default:
throw new Error('Unknown animal type'); // 如果类型未知,抛出错误
}
}
}
// 使用工厂模式创建对象
const factory = new AnimalFactory();
const dog = factory.createAnimal('dog'); // 创建 Dog 实例
console.log(dog.speak()); // 输出:Woof
const cat = factory.createAnimal('cat'); // 创建 Cat 实例
console.log(cat.speak()); // 输出:Meow单例模式
作用: 确保一个类只有一个实例,并提供一个全局访问点 实现: 如果存在实例则返回当前实例
js
// 定义一个 Logger 类
class Logger {
constructor() {
if (Logger.instance) {
return Logger.instance; // 如果已经存在实例,直接返回
}
this.messages = []; // 用于存储日志消息
Logger.instance = this; // 保存当前实例
}
log(message) {
this.messages.push(message); // 添加日志消息
}
getLogs() {
return this.messages; // 获取所有日志消息
}
}
// 使用单例模式
const logger1 = new Logger();
logger1.log('Hello'); // 添加日志
const logger2 = new Logger();
logger2.log('World'); // 添加日志
console.log(logger1.getLogs()); // 输出:["Hello", "World"]
console.log(logger1 === logger2); // 输出:true(logger1 和 logger2 是同一个实例)代理模式
作用: 通过创建一个代理对象来控制对实际对象的访问,代理对象可以添加额外的逻辑,比如权限检查、缓存、远程调用等
js
// 定义一个真实对象
class RealSubject {
request() {
return 'RealSubject: Handling request.'; // 真实对象的请求方法
}
}
// 定义一个代理对象
class Proxy {
constructor(realSubject) {
this.realSubject = realSubject; // 保存真实对象的引用
}
request() {
if (this.checkAccess()) {
// 检查权限
this.realSubject.request(); // 调用真实对象的请求方法
this.logAccess(); // 记录日志
}
}
checkAccess() {
console.log('Proxy: Logging the time of request.'); // 记录请求时间
return true; // 假设权限检查通过
}
logAccess() {
console.log('Proxy: Logging the request.'); // 记录请求
}
}
// 使用代理模式
const realSubject = new RealSubject(); // 创建真实对象
const proxy = new Proxy(realSubject); // 创建代理对象
proxy.request(); // 调用代理的请求方法观察者模式
作用: 一对多的依赖关系,让多个观察者对象同时监听某一个主题对象;当主题对象发生变化时,所有依赖它的观察者都会自动收到通知并进行更新
js
class Subject {
constructor(age) {
this.observers = [];
this._data = { name: '张三' };
this._data.age = age; // 假设这是他们要订阅的数据
console.log(this._data);
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter((item) => item !== observer);
}
notify() {
this.observers.forEach((observer) => observer.update(this._data));
}
// 修改数据的方法
setData(age) {
this._data.age = age;
this.notify(); // 数据变化后通知所有观察者
}
}
// 观察者1
class ObserverA {
update(data) {
console.log('观察者A收到更新:', data.age);
}
}
// 观察者2
class ObserverB {
update(data) {
console.log('观察者B收到更新:', `Hello, ${data.age}`);
}
}
// 使用示例
const subject = new Subject(23);
const a = new ObserverA();
const b = new ObserverB();
subject.addObserver(a);
subject.addObserver(b);
// 更新数据
subject.setData(25);策略模式
作用: 定义一系列算法,封装起来提供选择
js
// 定义一个上下文对象
class Context {
constructor(strategy) {
this.strategy = strategy; // 保存策略对象
}
executeStrategy(a, b) {
return this.strategy(a, b); // 执行策略
}
}
// 定义加法策略
function addStrategy(a, b) {
return a + b; // 加法运算
}
// 定义减法策略
function subtractStrategy(a, b) {
return a - b; // 减法运算
}
// 使用策略模式
const context = new Context(addStrategy); // 使用加法策略
console.log(context.executeStrategy(10, 5)); // 输出:15
context.strategy = subtractStrategy; // 切换到减法策略
console.log(context.executeStrategy(10, 5)); // 输出:5装饰器模式
作用: 通过组合的方式,动态地扩展对象的功能
js
class Components {
opertion() {
return '这是组件基类';
}
}
class CustomComponent extends Components {
opertion() {
return '这是自定义组件';
}
}
// 在不修改自定义组件方法的前提下新增新功能
class Decorator extends Components {
constructor(component) {
super();
this.component = component;
}
opertion() {
// ...添加新功能
console.log('装饰器添加的新功能...');
return '这是装饰器' + this.component.opertion();
}
}
const custom = new CustomComponent();
console.log(custom.opertion());
const decorator = new Decorator(custom);
console.log(decorator.opertion());适配器模式
作用: 将一个类的接口转换成客户希望的另一个接口,使原本不兼容的接口能够兼容
js
// 具体播放器 - MP3(原生支持)
class Mp3Player {
play(fileName) {
console.log(`MP3 Player: 正在播放文件 - ${fileName}`);
}
}
// 高级播放器 - VLC
class VlcPlayer {
play(fileName) {
console.log(`VLC Player: 正在播放 VLC 文件 - ${fileName}`);
}
}
// 高级播放器 - MP4
class Mp4Player {
play(fileName) {
console.log(`MP4 Player: 正在播放 MP4 文件 - ${fileName}`);
}
}
// 适配器统一接口
class MediaAdapter {
// 点击播放,根据不同类型去找到不同的播放器
static play(type, fileName) {
const player = this._getPlayer(type); // 根据播放类型获取播放器实例
if (player) {
player.play(fileName);
} else {
console.log('不支持的音频格式' + type);
}
}
// 私有方法:根据类型返回对应的播放器实例
static _getPlayer(audioType) {
switch (audioType.toLowerCase()) {
case 'mp3':
return new Mp3Player();
case 'vlc':
return new VlcPlayer();
case 'mp4':
return new Mp4Player();
default:
return null;
}
}
}
MediaAdapter.play('mp3', 'song.mp3'); //MP3 Player: 正在播放文件 - song.mp3
MediaAdapter.play('vlc', 'movie.vlc'); //VLC Player: 正在播放 VLC 文件 - movie.vlc
MediaAdapter.play('mp4', 'video.mp4'); //MP4 Player: 正在播放 MP4 文件 - video.mp4
MediaAdapter.play('avi', 'test.avi'); //不支持的音频格式avi模板模式
作用: 它定义了一个算法的骨架,并允许子类在不改变算法结构的前提下重新定义算法中的某些步骤 固定一个某个行为的流程框架,但是又有一些不同的步骤,把这些步骤抽离出来去分别实现,保证整体流程顺序不变
js
class Beverage {
// 固定模板方法
templateMethod() {
this.boilWater(); // 步骤1:烧水
this.brew(); // 步骤2:冲泡(每种饮料都是不同的冲泡方式,由子类实现)
this.pourInCup(); // 步骤3:倒进杯子里
this.addCondiments(); // 步骤4:加调料(每种饮料都是不同的调料,由子类实现)
}
boilWater() {
console.log('把水煮沸');
}
brew() {
throw new Error('子类必须实现 brew 冲泡方法');
}
pourInCup() {
console.log('倒入杯子');
}
addCondiments() {
throw new Error('子类必须实现 addCondiments 加调料方法');
}
}
class Coffee extends Beverage {
brew() {
console.log('用热水冲泡咖啡');
}
addCondiments() {
console.log('加糖和牛奶');
}
}
class Tea extends Beverage {
brew() {
console.log('用热水冲泡茶叶');
}
addCondiments() {
console.log('加柠檬');
}
}
// 制作饮料
class MakeBeverage {
constructor(beverage) {
this.beverage = beverage;
this.beverage.templateMethod();
}
}
console.log(' ********** 制作咖啡 ********** ');
const coffee = new MakeBeverage(new Coffee());
/*
把水煮沸
用热水冲泡咖啡
倒入杯子
加糖和牛奶
*/
console.log(' ********** 制作茶 ********** ');
const tea = new MakeBeverage(new Tea());
/*
把水煮沸
用热水冲泡茶叶
倒入杯子
加柠檬
*/建造者模式
作用: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 把一个复杂的问题简单化分离出来,逐步去构建整体
js
// 定义一个复杂对象
class Car {
constructor() {
this.type = null; // 车型
this.seats = null; // 座位数
this.engine = null; // 发动机类型
this.tripComputer = null; // 是否有行程计算机
this.gps = null; // 是否有 GPS
}
}
// 定义一个建造者类
class CarBuilder {
constructor() {
this.car = new Car(); // 创建一个 Car 实例
}
setType(type) {
this.car.type = type; // 设置车型
return this; // 返回当前对象,支持链式调用
}
setSeats(seats) {
this.car.seats = seats; // 设置座位数
return this; // 返回当前对象,支持链式调用
}
setEngine(engine) {
this.car.engine = engine; // 设置发动机类型
return this; // 返回当前对象,支持链式调用
}
setTripComputer(tripComputer) {
this.car.tripComputer = tripComputer; // 设置行程计算机
return this; // 返回当前对象,支持链式调用
}
setGPS(gps) {
this.car.gps = gps; // 设置 GPS
return this; // 返回当前对象,支持链式调用
}
build() {
return this.car; // 返回构建好的 Car 实例
}
}
// 使用建造者模式
const carBuilder = new CarBuilder(); // 创建建造者对象
const car = carBuilder
.setType('SUV') // 设置车型为 SUV
.setSeats(4) // 设置座位数为 4
.setEngine('V6') // 设置发动机类型为 V6
.setTripComputer(true) // 设置行程计算机为 true
.setGPS(true) // 设置 GPS 为 true
.build(); // 构建汽车
console.log(car); // 输出构建好的汽车对象