typescript - Je možné abstraktně oddělit singleton pattern od samotné třídy?
Prací s typescript/javascript jsem vytvořil kolekci singletonů.
Nicméně při pokusu o refaktoring a abstrakci implementace jsem se pokusil připravit třídu, která bude implementovat logiku singletonu a pro ně k rozšíření. To bylo očividně naivní z mé strany, protože situace vede k problémům s konstruktorem a zdá se být nerealizovatelná.
Takže moje otázka je, zda je možné elegantně aplikovat chování singletonu na kolekci tříd/objektů?
V následujícím kódu by bylo ze samotné čitelnosti hezké oddělit logiku singletonu. Dále bych chtěl konkrétně přinutit ostatní třídy v této kolekci, protože je přidávají přispěvatelé, aby je implementovaly jako singletony. Bylo by to trochu hezčí udělat jen prostřednictvím „zapojující“ nějakou abstraktní rozšířenou třídu nebo nějaký druh wrapperu.
class Car {
/* Singleton Implementation Start */
private static _instance: Car;
private constructor() {}
public static getInstance(): Car {
if (!Car._instance) {
Car._instance = new Car();
}
return Car._instance;
}
/* Singleton Implementation End */
private _name = "Audi"
private _color = 'red';
private _maxSpeed = 150;
drive(){
console.log(`WOW! You are riding your cool ${this._color} ${this._name} at ${150} kmh!` )
}
paint(color: string){
this._color = color;
}
}
class Plane {
/* Singleton Implementation Start */
private static _instance: Plane;
private constructor() {}
public static getInstance(): Plane {
if (!Plane._instance) {
Plane._instance = new Plane();
}
return Plane._instance;
}
/* Singleton Implementation End */
private _motors = 4;
private _maxSpeed = 550;
fly(){
console.log(`WOW! You are flying your plane with roaring ${_motors} motors at ${150} kmh!` )
}
}
Odpověď č. 1
Pokud vytvoříme tovární funkci, která přijímá generický typ:
function Singleton<T>() {
return class Singleton {
static instance: T; // must be public
protected constructor() {}
public static getInstance(): T {
if (!this.instance) this.instance = new this() as T;
return this.instance;
}
}
}
Pak můžeme rozšířit vrácenou třídu a poskytnout generiku jako samotnou třídu:
class Car extends Singleton<Car>() {
private _name = "Audi"
private _color = 'red';
private _maxSpeed = 150;
drive(){
console.log(`WOW! You are riding your cool ${this._color} ${this._name} at ${150} kmh!` )
}
paint(color: string){
this._color = color;
}
}
Toto musí být provedeno funkcí, protože statické členy nemohou odkazovat na parametr typu třídy. Další nevýhodou je, že nemůžete mít žádné soukromé nebo chráněné členy.
Dětské hřiště
