假设我用面向对象语言(例如Python)实现了以下设计。我知道 OO 方式有点不自然,有时在使用 TypeScript 时不是首选。那么在 TypeScript 中实现相同设计的惯用方法是什么?
想法是:
Car
类型来描述通用汽车。Car
类型,并且Car
类型。这将是 Python 代码:
from abc import ABC, abstractmethod
import json
class Car(ABC):
@abstractmethod
def start(self):
raise NotImplemented
class ManualGearboxCar(Car):
def start(self):
self.engage_clutch()
self.start_engine()
dashboard_info = self.read_dashboard()
print("Dashboard:", json.dumps(dashboard_info))
# ... Check dashboard_info and raise if anything goes wrong ...
if not dashboard_info["ok"]:
raise Exception("Something is not OK")
self.shift_gear(1)
self.release_clutch()
print("Car started!")
def read_dashboard(self) -> dict:
return {
"foo": "bar",
"default": "values",
"ok": True,
}
def engage_clutch(self):
print("[DefaultClutch] engaged!")
def release_clutch(self):
print("[DefaultClutch] released!")
@abstractmethod
def start_engine(self):
raise NotImplemented
@abstractmethod
def shift_gear(self, level: int):
raise NotImplemented
class Picasso(ManualGearboxCar):
def read_dashboard(self) -> dict:
info = super().read_dashboard()
return info | {
"brand": "Citroen",
}
def start_engine(self):
print("[Picasso] engine started!")
def shift_gear(self, level: int):
print("[Picasso] gear shifted to:", level)
class Tesla(Car):
def start(self):
print("[Tesla] Wow it just starts!")
if __name__ == "__main__":
picasso = Picasso()
picasso.start()
tesla = Tesla()
tesla.start()
这是我在 TypeScript 中实现相同功能的想法,但我觉得它有点奇怪,而且不是原生的......
type Car = {
start(): void;
}
abstract class ManualGearCar implements Car {
start(): void {
this.engageClutch();
this.startEngine();
const dashboardInfo = this.readDashboard();
// ... Check dashboard_info and raise if anything goes wrong ...
console.log(`Dashboard: ${JSON.stringify(dashboardInfo)}`);
if (!dashboardInfo.ok) {
throw new Error("Something is not OK");
}
this.shiftGear(1);
this.releaseClutch();
console.log("Car started!");
}
readDashboard(): Record<string, any> & { ok: boolean } {
return {
foo: "bar",
default: "values",
ok: true,
};
}
engageClutch(): void {
console.log("[DefaultClutch] engaged!");
}
releaseClutch(): void {
console.log("[DefaultClutch] released!");
}
abstract startEngine(): void;
abstract shiftGear(level: number): void;
}
class Picasso extends ManualGearCar {
readDashboard(): Record<string, any> & { ok: boolean; } {
const info = super.readDashboard();
return { ...info, brand: "Citroen" };
}
startEngine(): void {
console.log("[Picasso] engine started!");
}
shiftGear(level: number): void {
console.log(`[Picasso] gear shifted to: ${level}`);
}
}
const createPicasso = (): Car => {
return new Picasso();
}
const createTesla = (): Car => {
return {
start() {
console.log("[Tesla] Wow it just starts!");
}
}
}
function main() {
const picasso = createPicasso();
picasso.start();
const tesla = createTesla();
tesla.start()
}
main();
你会用惯用的 TypeScript 做什么?
谢谢!
看起来您正在描述模板方法模式。
如果您喜欢更实用的风格,就像许多其他设计模式一样,这可以使用高阶函数轻松实现。然后,您可以将函数作为参数传递来代替抽象方法。