js的一些设计模式概念记录
工厂模式
function createPerson(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name);
};
return o;
}
let person1 = createPerson("Nicholas", 29, "Software Engineer");
let person2 = createPerson("Greg", 27, "Doctor");
工厂模式可以解决创建多个类似对象的问题,但是没有解决对象标识问题
构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
};
}
let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg
Person()构造函数代替了createPerson()工厂函数基本一样,但是有以下区别
- 没有显示地创建对象
- 属性和方法直接赋值给了this
- 没有return
使用new操作符。以这种方式调用构造函数会执行如下操作
1.内存中创建一个新对象
2.这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性
3.构造函数内部的this被赋值为这个新对象(即this指向新对象)
4.执行构造函数内部的代码(给新对象添加属性)
5.如果构造函数返回非空对象,则返回该对象;否则返回刚创建的新对象。
构造函数模式解决了对象标识问题,但是没有解决在构造函数内部定义的方法会被多次实例化,不同实例上的函数虽然同名确不相同。
原型模式
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
let person1 = new Person();
person1.sayName(); // "Nicholas"
let person2 = new Person();
person2.sayName(); // "Nicholas"
console.log(person1.sayName == person2.sayName); // true
策略模式
策略模式是一种行为型设计模式,它允许我们定义一组算法,并将每个算法都封装起来,使它们可以互换使用。这样,我们可以在运行时动态地切换对象的算法。
下面是一个用JavaScript实现策略模式的例子,假设我们正在开发一个游戏,需要根据玩家的不同技能,计算不同的攻击力。我们可以使用策略模式来实现:
// 定义计算攻击力的策略类
class AttackStrategy {
constructor() {}
calculateAttack() {}
}
// 定义不同的计算攻击力的策略类
class BasicAttackStrategy extends AttackStrategy {
constructor() {
super();
}
calculateAttack() {
return 10;
}
}
class MagicAttackStrategy extends AttackStrategy {
constructor() {
super();
}
calculateAttack() {
return 20;
}
}
class SuperAttackStrategy extends AttackStrategy {
constructor() {
super();
}
calculateAttack() {
return 50;
}
}
// 定义玩家类
class Player {
constructor(attackStrategy) {
this.attackStrategy = attackStrategy;
}
attack() {
return this.attackStrategy.calculateAttack();
}
setAttackStrategy(attackStrategy) {
this.attackStrategy = attackStrategy;
}
}
// 创建玩家对象
const player1 = new Player(new BasicAttackStrategy());
console.log(player1.attack()); // 输出 10
// 切换攻击策略
player1.setAttackStrategy(new MagicAttackStrategy());
console.log(player1.attack()); // 输出 20
// 切换攻击策略
player1.setAttackStrategy(new SuperAttackStrategy());
console.log(player1.attack()); // 输出 50
在这个例子中,我们定义了一个AttackStrategy策略类,并创建了三个不同的子类来计算攻击力。然后,我们定义了一个Player类,该类接受一个AttackStrategy对象作为参数,并且通过调用calculateAttack()方法来计算攻击力。最后,我们可以创建一个玩家对象,并根据需要切换不同的攻击策略。
这种方式下,我们可以轻松地添加新的攻击策略,而不需要修改Player类的代码。同时,我们也可以在运行时动态地切换攻击策略,从而获得更好的灵活性。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2021-03-09 伪类选择器和伪元素选择器的区别