在我的一个个人项目中,我试图设计一些对象和列表类型。对象和列表应该是可序列化的(即有一个toJSON()
和fromJSON()
方法)。示例对象和列表将具有以下基本代码:
type IPerson = {
id: number;
name: string;
// additional properties
}
class Person {
id: number;
name: string;
// additional properties
constructor(id: number, name: string, ...) { ... }
toJSON(): IPerson { return { ... } }
static fromJSON(json: IPerson): Person { return new Person(...) }
// additional methods
}
class PersonList {
list: Person[];
constructor(list: Person[]) { ... }
findById(id: number) { return this.list.find(it => it.id === id) }
findByName(name: string) { return this.list.find(it => it.name === name) }
add(person: Person) { this.list.push(person) }
remove(person: Person) { this.list = this.list.filter(it => it !== person) }
toJSON(): IPerson[] { return this.list.map(it => it.toJSON()) }
static fromJSON(json: IPerson[]): PersonList { return new PersonList(json.map(it => Person.fromJSON(it))) }
// additional methods
}
我使用的所有对象和列表至少都有这里列出的方法。
现在我试图将其转换为通用解决方案,以便:
type JSON = {
id: number;
name: string;
}
abstract class BaseObject<T extends JSON> {
abstract get id();
abstract get name();
constructor(id: number, name: string) { ... }
abstract toJSON(): T
abstract static fromJSON(json: T): BaseObject<T>
}
class BaseList<T, U> {
list: BaseObject<T>[];
constructor(list: BaseObject<T>[]) { ... }
findById(id: number) { return this.list.find(it => it.id === id) }
findByName(name: string) { return this.list.find(it => it.name === name) }
add(obj: BaseObject<T>) { this.list.push(obj) }
remove(obj: BaseObject<T>) { this.list = this.list.filter(it => it !== obj) }
toJSON(): U[] { return this.list.map(it => it.toJSON()) }
static fromJSON(json: U[]): BaseList<T, U> { return new BaseList<T, U>(json.map(it => BaseObject<T>.fromJSON(it))) }
}
如果这个结构起作用(它没有),它会使我的生活如此简单:
type IPerson = JSON & {
// additional fields
}
class Person extends BaseObject<IPerson> {
get id() { ... }
get name() { ... }
// additional getters for other fields
toJSON(): IPerson { return { ... } }
static fromJSON(json: IPerson): Person { return new Person(...) }
// additional methods
}
class PersonList extends BaseList<Person, IPerson> {
// additional methods
}
// other object and list types definitions follow
然而,我的解决方案在以下几点上失败了:
BaseObject
不能有抽象静态fromJSON()
方法。BaseList
不能有抽象静态fromJSON()
方法。BaseList.fromJSON()
不能实例化新列表,也不能调用BaseObject.fromJSON()
来实例化新对象。我怎样才能避开这些问题?有没有更好的设计模式,我在这里错过了?
最佳答案
由于我不能定义静态抽象函数,这里是我所采用的实现方式:
type BaseJson = {
id: string;
}
abstract class BaseObj<U> {
abstract get id(): string;
abstract toJSON(): U;
}
abstract class BaseList<T extends BaseObj<U>, U> {
list: BaseObj<U>[] = [];
add(x: BaseObj<U>) { this.list.push(x) }
remove(x: BaseObj<U>) { this.list = this.list.filter(it => it !== x) }
toJSON(): U[] { return this.list.map(it => it.toJSON()) }
}
type IPerson = BaseJson & {
name: string;
}
class Person extends BaseObj<IPerson> {
data: IPerson;
constructor(data: IPerson) { super(); this.data = data }
get id() { return this.data.id }
get name() { return this.data.name }
toJSON(): IPerson { return { id: this.id, name: this.name } }
static fromJSON(json: IPerson): Person { return new Person(json) }
}
class PersonList extends BaseList<Person, IPerson> {
constructor(list: Person[]) { super(); this.list = list }
static fromJSON(json: IPerson[]): PersonList { return new PersonList(json.map(it => Person.fromJSON(it))) }
}
底线:我必须在所有的对象和列表类中定义静态
fromJSON()
方法。这些方法并不复杂,所以它是一种舒适的双赢。=)