根据 class 内容创建 child class
Creating child class based on class content
我有这样的 class 结构:
LineTemplate (abstract)
/ \
LineOut (abstract) LineIn (final)
/ \
LineOutTransfers (final) LineOutSells (final)
LineOut 和 LineIn 都应该从文件中读取一行,对照数据库检查其内容并 运行 多个查询。
然而,LineOut 包含两个略有不同的变体,这取决于行的内容。由于 LineOutTransfers 和 LineOutSells 在调用它们的方法时执行不同的操作,我决定继承并将它们视为 subclasses.
我在LineTemplate中创建了一个public静态LineTemplate __init()方法来判断是否是LineOut 或 LineIn class 和 return 基于外部条件的正确类型,我想实现一个类似的确定 LineOut subclass.
正确类型的方法
由于 LineOut child 取决于行内容,但是,我卡在了这一点上。 class 应该读取该行,然后将其自身转换为正确的 child 然后执行检查。但这是不可能的,因为我无法将 parent class 转换为 child,如果它还不是那种类型( 多态性 )。
我也想过读取LineOut的__init()方法里面的所有行,然后通过变量作为其 child 构造函数的参数,但由于有一堆变量要读取,并且由于它在 LineIn 中的完成方式不同,在我看来这是一个不好的做法.
有什么想法吗?提前致谢。
也许工厂方法对这种情况有用:https://refactoring.guru/design-patterns/factory-method
您能否向 LineOut
添加一个 convertWithContext(SomeClassRepresentingContext ctx)
方法,这将 return 一个新的 LineOut
作为 LineOut 的正确子 class?
另一种方法是使用工厂方法并为其提供行内容和上下文。像
LineOutFactory.instance().constructLineOut(String line, SomeClassRepresentingContext ctx);
在 Java 中,您无法更改 class 的类型,一旦创建,您只能根据现有 class 的内容构建新的 class可能还有外部环境。
比继承更喜欢组合,所以而不是
abstract class LineOut {
public void consume(Line l) {
// ...
subclassConsume(l);
// ...
}
protected abstract void subclassConsume(Line l);
}
// and
class LineOutTransfers extends LineOut {
protected abstract void subclassConsume(Line l) { ... }
}
class LineOutSells extends LineOut {
protected abstract void subclassConsume(Line l) { ... }
}
你应该这样做
abstract class LineOut {
private TransferLineHandler transferHandler;
private SellsLineHandler sellsHandler;
public void consume(Line l) {
// ...
if (isTransfer(l)) {
transferHandler.consume(l);
} else {
sellsHandler.consume(l);
}
// ...
}
protected abstract void subclassConsume(Line l);
}
// with
class TransferLineHandler {
public consume(l) { // stuff from LineOutTransfers }
}
class SellsLineHandler {
public consume(l) { // stuff from LineOutSells }
}
这完全消除了“动态子类化”问题并使代码更易于测试。
我有这样的 class 结构:
LineTemplate (abstract)
/ \
LineOut (abstract) LineIn (final)
/ \
LineOutTransfers (final) LineOutSells (final)
LineOut 和 LineIn 都应该从文件中读取一行,对照数据库检查其内容并 运行 多个查询。
然而,LineOut 包含两个略有不同的变体,这取决于行的内容。由于 LineOutTransfers 和 LineOutSells 在调用它们的方法时执行不同的操作,我决定继承并将它们视为 subclasses.
我在LineTemplate中创建了一个public静态LineTemplate __init()方法来判断是否是LineOut 或 LineIn class 和 return 基于外部条件的正确类型,我想实现一个类似的确定 LineOut subclass.
正确类型的方法由于 LineOut child 取决于行内容,但是,我卡在了这一点上。 class 应该读取该行,然后将其自身转换为正确的 child 然后执行检查。但这是不可能的,因为我无法将 parent class 转换为 child,如果它还不是那种类型( 多态性 )。
我也想过读取LineOut的__init()方法里面的所有行,然后通过变量作为其 child 构造函数的参数,但由于有一堆变量要读取,并且由于它在 LineIn 中的完成方式不同,在我看来这是一个不好的做法.
有什么想法吗?提前致谢。
也许工厂方法对这种情况有用:https://refactoring.guru/design-patterns/factory-method
您能否向 LineOut
添加一个 convertWithContext(SomeClassRepresentingContext ctx)
方法,这将 return 一个新的 LineOut
作为 LineOut 的正确子 class?
另一种方法是使用工厂方法并为其提供行内容和上下文。像
LineOutFactory.instance().constructLineOut(String line, SomeClassRepresentingContext ctx);
在 Java 中,您无法更改 class 的类型,一旦创建,您只能根据现有 class 的内容构建新的 class可能还有外部环境。
比继承更喜欢组合,所以而不是
abstract class LineOut {
public void consume(Line l) {
// ...
subclassConsume(l);
// ...
}
protected abstract void subclassConsume(Line l);
}
// and
class LineOutTransfers extends LineOut {
protected abstract void subclassConsume(Line l) { ... }
}
class LineOutSells extends LineOut {
protected abstract void subclassConsume(Line l) { ... }
}
你应该这样做
abstract class LineOut {
private TransferLineHandler transferHandler;
private SellsLineHandler sellsHandler;
public void consume(Line l) {
// ...
if (isTransfer(l)) {
transferHandler.consume(l);
} else {
sellsHandler.consume(l);
}
// ...
}
protected abstract void subclassConsume(Line l);
}
// with
class TransferLineHandler {
public consume(l) { // stuff from LineOutTransfers }
}
class SellsLineHandler {
public consume(l) { // stuff from LineOutSells }
}
这完全消除了“动态子类化”问题并使代码更易于测试。