В каких случаях вы бы стали наследовать класс, а в каких внедряли бы поле тип объекта?
Например:
"Импульсный" и "Цифровой" счетчик различаются по набору полей.
"Водяной счетчик" может быть как цифровым так и импульсным.
Однако чтоб получить "Водяной счетчик".data я должен поработать с полями импульсного счетчика или цифрового или интегрированного или... или ..
Напрашивается что-то вроде поля type в "Счетчик" тогда в коде можно оперировать с такими данными через switch, что сократит количество кода. Но тогда где определять эти "дополнительные" поля..
Постарался отобразить в коде суть вопроса.
// TypeScript not works on stackoverflow.
// Первый пример
abstract class Counter {
constructor(protected serialNumber: string) {}
getData(data: number): number {
return data;
};
}
class ImpulseCounter extends Counter {
constructor(
private initCounter: number,
private multipler: number,
serialNumber,
) {
super(serialNumber)
}
getData(data) {
this.initCounter + this.multipler * data;
}
}
class WaterImpulseCounter extends ImpulseCounter {
constructor(
private hot: boolean,
initCounter,
multipler,
serialNumber
) {
super(initCounter, multipler, serialNumber);
}
getData(data) {
if (this.hot) {
return this.super.getData(data) * 0.1
} else {
return this.super.getData(data)
}
}
}
class DigitalCounter extends Counter {
constructor(
private address: string,
serialNumber
) {
super(serialNumber)
}
getData() {
this.super.getData();
}
}
class WaterDigitalCounter extends DigitalCounter {
constructor(private hot: boolean,
address,
serialNumber
) {
super(address, serialNumber)
}
getData(data) { // Дублирование кода, тупик.
if (this.hot) {
return this.super.getData(data) * 0.1
} else {
return this.super.getData(data)
}
}
}
// Второй пример
enum DataTypes = {
Impulse,
Digital
}
abstract class Counter {
constructor(
protected serialNumber: string,
protected dataType: DataTypes
) {}
getData(data) {
switch (this.dataType) { // В каком месте(классе) нужно определять switch логику и поля this.initCounter, this.multipler
case (DataTypes.Impulse):
{
return this.initCounter + this.multipler * data;
}
}
return data;
};
}
class WaterCounter extends Counter {
hot: false;
constructor(
serialNumber,
dataType: DataTypes
) {
super(serialNumber, dataType)
}
getData(data) {
if (this.hot) {
return this.super.getData(data) * 0.1
} else {
return this.super.getData(data)
}
}
}
Ответ
Например: "Импульсный" и "Цифровой" счетчик различаются по набору полей. "Водяной счетчик" может быть как цифровым так и импульсным.
Пока это описание хрестоматийной мотивации использовать паттерн «Декоратор»:
class WaterCounter extends Counter {
constructor(
private impl: *Counter
hot: bool
serialNumber,
) {
super(serialNumber)
}
getData(data: number): number {
data=impl->data;
return this.hot ? data * 0.1 : data;
};
}
//...
waterImpulseCounter = new WaterCounter(new ImpulseCoubter(..., 0), hot, serial);
digitalImpulseCounter = new WaterCounter(new DigitalCoubter(..., 0), hot, serial);
Но тут во-первых непонятно, что делать с серийником внутренних классов, а во-вторых немного страдает логика поведения: теперь возможно создать водный счётчик, который может использовать другой водный счётчик, так что помня основное правило, надо отделить реализацию от интерфейса; в итоге получится столь же хрестоматийный «мост»:
abstract class CounterImpl {
constructor() {}
getData(data: number): number {
return data;
};
}
class ImpulseCounter extends CounterImpl {
constructor(
private initCounter: number,
private multipler: number,
) { }
getData(data) {
this.initCounter + this.multipler * data;
}
}
class DigitalCounter extends CounterImpl {
constructor(
private address: string,
) { }
getData() {
this.super.getData();
}
}
abstract class Counter {
constructor(protected serialNumber: string
private impl: *CounterImpl
) { }
getData(data: number): number {
return impl->getData(data);
};
}
class WaterCounter extends Counter {
constructor(
hot: bool
serialNumber,
) {
super(impl, serialNumber)
}
getData(data: number): number {
return this.super.getData(data) * (this.hot ? 0.1 : 1);
};
}
Комментариев нет:
Отправить комментарий