设计到模式
设计模式 是软件开发中一套被反复验证、用于解决特定场景下通用问题的 “最佳实践模板”。它不是现成的代码,而是一种可复用的设计思路
根据设计,即是一种思想,模式相当于一种固定的模板,也就是从设计到模式。
1.遇到具体问题
遇到一个问题:页面中多次点击 “打开弹窗” 按钮,每次都会创建一个新的弹窗 DOM 节点,导致页面出现多个重复弹窗,既浪费资源又影响体验。
2. 设计思想(解决思路)
针对这个问题,思考出核心设计思想: “确保某个对象在程序生命周期内只有一个实例,重复调用时直接返回已存在的实例,而非新建” 。这个思想是抽象的 —— 它只规定了 “要做什么”,但没说 “具体怎么做”。
3. 模式模板(具象化实现)
基于这个设计思想,结合 JavaScript 的特性(闭包、立即执行函数),封装出一套可复用的 “模式模板“
思想是根,模式是果。设计模式的本质是「抽象设计思想」→「具象模式模板」的转化:思想解决 “为什么做”,模板解决 “怎么做”。这里就需要需结合业务场景灵活适配,避免僵化套用。
题目1:
外出打车,可选专车和快车,不同车价格不同,快车每公里1元,专车每公里2元,行程开始显示车辆信息,结束显示支付金额。
1.专车和快车有公共的特性,可以提取出来,车牌,颜色等
创建一个父类:Car
2.专车和快车有自己单独的价格属性
创建一个kuaiChe和zhuanche类,继承Car
3.行程是当前开始接单到结束状态
创建一个Trip类,有单独的行程方法
实现行程中的信息:
class Car {
constructor(number,name){
this.number = number
this.name = name
}
}
class Kuaiche extends Car {
constructor(number,name) {
super(number,name)
this.price =1
}
}
class zhuanche extends Car{
constructor(number,name) {
super(number,name)
this.price =2
}
}
class Trip {
constructor(car) {
this.car = car
}
start(){
console.log('行程开始'+this.car.name)
}
end(){
console.log('行程结束,价格'+(this.car.price*10))
}
}
let car = new KuaiChe(10291,'宝马')
let trip = new Trip(car)
trip.start()
trip.end()
-
第一步:
new KuaiChe(10291, '宝马')创建实例:- 调用
KuaiChe的构造函数,先执行super(number, name)→ 调用父类Car的构造函数; Car的构造函数给实例赋值this.number = 10291、this.name = '宝马';- 回到
KuaiChe的构造函数,给实例赋值this.price = 1; - 最终
car实例的结构是:{ number: 10291, name: '宝马', price: 1 }。
- 调用
-
第二步:
new Trip(car)创建行程实例:Trip的构造函数接收第一步的car实例,并存为this.car;- 此时
trip实例的结构是:{ car: { number: 10291, name: '宝马', price: 1 } }。
-
第三步:
trip.start()/trip.end()访问属性:-
this.car.name→ 直接访问trip持有的car实例的name属性(这个属性是KuaiChe继承自Car并初始化的); -
this.car.price→ 访问KuaiChe自身定义的price属性; -
整个过程中,
Trip只是 “借用” 了car实例的属性,而非自己继承了Car的属性。class Car { constructor(number, name) { this.number = number; this.name = name; } // 定义在Car原型上的方法 getCarInfo() { return `${this.name}(${this.number})`; } } class KuaiChe extends Car { constructor(number, name){ super(number, name); this.price = 1; } } const car = new KuaiChe(10291, '宝马'); // 访问原型链上的方法:car自己没有getCarInfo,就往上找Car的原型 console.log(car.getCarInfo()); // 输出:宝马(10291)
当访问
car.getCarInfo时,JS 引擎会先看car实例自己有没有getCarInfo,如果没有(比如你没在Car里定义),才会沿着原型链往上找父类Car的原型,这就是 “原型链查找”. -