我有一个用于处理数据的类,该数据可能来自不同的来源。我需要将数据应该从那里传递给源。所以,我想问,什么是正确的方法:
全部传递一个变量,并按变量类型检查源-更少的代码而不是那么复杂- processDataB
使用方法的单独变量不是一种情况-我需要将此值通过许多类/选项传递给目标类
示例:
interface DataProviderSource {
dataURL?: string;
dataArchive?: ArrayBuffer;
}
processDataA(source: DataProviderSource) {
if (source.dataURL) {
...
} else if (source.dataArchive) {
...
} else {
...
}
}
processDataB(source: ArrayBuffer | string) {
if (source instanceof ArrayBuffer) {
...
} else if (typeof source === "string") {
...
} else {
...
}
}
答案 0 :(得分:1)
要避免的一件事是拥有这样的弱接口:
interface DataProviderSource {
dataURL?: string;
dataArchive?: ArrayBuffer;
}
因为-因为每个属性都是可选的-所以它允许传递一个空对象。我们不希望那样—我们只希望传递一种格式的数据。
这是一个品味问题。一种方法是:
class Processor {
static fromArrayBuffer(source: ArrayBuffer) {}
static fromString(source: string) {}
process(source: string | ArrayBuffer) {
if (source instanceof ArrayBuffer) {
return Processor.fromArrayBuffer(source);
}
return Processor.fromString(source);
}
}
这很简单,但是它破坏了打开/关闭的原理。您还可以使用命名构造函数对源进行建模。在这种设计中,每种类型的信号源都配备有自己的处理器。
interface Source<T = any> {
data: T;
process: () => void;
}
class DataURL implements Source<string> {
constructor(readonly data: string) {
this.data = data;
};
process() {}
}
class Archieve implements Source<ArrayBuffer> {
constructor(readonly data: ArrayBuffer) {
this.data = data;
};
process() {}
}
class SomeOther implements Source<string> {
constructor(readonly data: string) {
this.data = data;
};
process() {}
}
此解决方案可供扩展。唯一重要的是源代码实现Source
接口。
const process = (...sources: Source[]): void =>
sources.forEach(source => source.process())
process(
new DataURL('hello'),
new Archieve(new ArrayBuffer(32)),
new SomeOther('world')
);