根据另一个对象的类型选择要创建的对象类型是否有任何通用策略
Are there any common strategies for choosing an object type to create based on the type of another object
假设我有一个对象,它可以是多种不同类型中的任何一种,而这些类型都派生自一个基本类型。我想创建第二个对象,它与第一个对象相关,因为它的类型取决于第一个对象的类型。然而,第二个对象的类型将始终从第二个基 class.
派生
我的解决方案是让第一个对象通过虚拟方法创建第二个对象。
然而,在这种特殊情况下,我们根本不希望两个 class 耦合。两个对象都不应存在另一个对象。
这意味着必须有某种第三方中介对象根据第一个对象类型创建第二个对象。
因此,我选择的下一个解决方案是让这个中介成为一个工厂,它专门查看第一个对象的类型并根据它实例化第二个对象。
对我来说这可行,但似乎不是一个理想的解决方案。如果工厂正在创建第一个对象,那么无论何时添加新的派生类型,都必须更新两个工厂并建立新的连接。
是否有任何通用的设计模式可以帮助解决这个问题并使代码更清晰?
编辑:如@MustehssunIqbal 所述。此问题是并行层次结构的 classic 案例。通过创建桥接或类似方法解决此问题的问题是两个 classes 需要保持解耦。
提供具体示例:
假设我有一个基本处理器 class,它被许多处理器子 class 继承。这对于当前的应用程序来说很好。然而,一个新的应用程序也想使用这些 classes,这是一个 GUI 应用程序。此应用程序想要为每个处理器创建一个 GUI 元素,并且每个单独类型的处理器也必须具有特定的 GUI 类型。
现在要停止在第一个应用程序中需要 GUI,处理器和 GUI classes 必须分离。
我从来没有故意使用它,但 Prototype pattern 可能适合你。
或者,使用反射* 在运行时查看第一个对象是什么类型,并使用该信息来决定为第二个对象构建什么类型。
- Reflection 是 .Net 中一个概念的名称,我怀疑它在其他语言中会有类似的实现。
考虑到静态映射没问题,我会将其作为配置文件保存,其中包含 类.
的完全限定名称对
然后我会在运行时将此配置读入 Map 结构,其中键是第一个或主要对象。对于每个对象,我将搜索 Map 结构并在给定第一个对象的完全限定名称的情况下找到相应的关联第二个对象。在此之后我只需要实例化第二个对象:
Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });
或
Class<?> clazz = Class.forName(whichClass);
Object object = clazz.newInstance();
如果需要,也可以将对象转换为相应的 Class。
这将使您能够使映射远离代码(在配置文件中简单定义),并且可以在需要时轻松更改。
问题 Creating an instance using the class name and calling constructor 读起来可能很有趣。
P.S.: 我假设示例是 Java 但我想这也可以用其他 OO 语言来完成。
感谢您提供详细信息。这似乎是平行层次结构的情况。您有许多 UI 元素,例如按钮、列表 - 但在绘制这些元素时,您有三个按钮用于三个处理器,三个 TextAreas 用于三个处理器,等等。
如评论中所述,我建议实施桥接模式,其中可以抽象出特定于不同处理器的事物。 ProcessorRenderer(下图)是抽象出来的东西,可以被UI层使用。
另一种类似的方法是使用应用程序外观层。正如您在编辑中提到的,您需要将处理器层次结构与 UI 层分开。我也同意这一点。我不希望 UI 层知道有关处理器的任何信息(或来自域层的任何信息)。 UI 层应该是哑的,它应该只绘制按钮、列表、单选按钮等东西。所以我建议引入一个 Application Facade 层,它会从域层了解处理器层次结构,并且会知道 UI 层中不同类型的 UI 元素,但不应该知道“如何绘制 UI 元素” -> 那部分应该只有笨蛋才知道 UI 层。 UI 层是可测试的,与域无关,而域对 UI 一无所知。
Application Facade层包含的是将Domain层对象转换为UI层可以使用的数据结构。您可以在此处阅读有关应用程序外观的更多信息:https://www.martinfowler.com/apsupp/appfacades.pdf
桥梁模式:https://en.wikipedia.org/wiki/Bridge_pattern
我在这里将 Application Facade 视为 Bridge 模式的一个特例,除了 Application Facade (ProcessorRenderer) 依赖于 UI 层,而在 Bridge 模式中依赖是相反的.但这只是我的意见。
我在这里驳回了使用访问者模式的想法,因为您在编辑中提到您希望将 UI 层与处理器层次结构完全分离。也因为如果在层次结构中所做的一切都是渲染,那么只有一个 Visitor 的实现,即 RenderingVisitor。那完全没问题,但我认为让它成为访客就太过分了。但是,如果您在不同类型的处理器上有许多这样的不同操作,其中每种处理器的每个操作都不同,那么我建议改用访问者模式。 :)
假设我有一个对象,它可以是多种不同类型中的任何一种,而这些类型都派生自一个基本类型。我想创建第二个对象,它与第一个对象相关,因为它的类型取决于第一个对象的类型。然而,第二个对象的类型将始终从第二个基 class.
派生我的解决方案是让第一个对象通过虚拟方法创建第二个对象。
然而,在这种特殊情况下,我们根本不希望两个 class 耦合。两个对象都不应存在另一个对象。
这意味着必须有某种第三方中介对象根据第一个对象类型创建第二个对象。
因此,我选择的下一个解决方案是让这个中介成为一个工厂,它专门查看第一个对象的类型并根据它实例化第二个对象。
对我来说这可行,但似乎不是一个理想的解决方案。如果工厂正在创建第一个对象,那么无论何时添加新的派生类型,都必须更新两个工厂并建立新的连接。
是否有任何通用的设计模式可以帮助解决这个问题并使代码更清晰?
编辑:如@MustehssunIqbal 所述。此问题是并行层次结构的 classic 案例。通过创建桥接或类似方法解决此问题的问题是两个 classes 需要保持解耦。
提供具体示例:
假设我有一个基本处理器 class,它被许多处理器子 class 继承。这对于当前的应用程序来说很好。然而,一个新的应用程序也想使用这些 classes,这是一个 GUI 应用程序。此应用程序想要为每个处理器创建一个 GUI 元素,并且每个单独类型的处理器也必须具有特定的 GUI 类型。
现在要停止在第一个应用程序中需要 GUI,处理器和 GUI classes 必须分离。
我从来没有故意使用它,但 Prototype pattern 可能适合你。
或者,使用反射* 在运行时查看第一个对象是什么类型,并使用该信息来决定为第二个对象构建什么类型。
- Reflection 是 .Net 中一个概念的名称,我怀疑它在其他语言中会有类似的实现。
考虑到静态映射没问题,我会将其作为配置文件保存,其中包含 类.
的完全限定名称对然后我会在运行时将此配置读入 Map 结构,其中键是第一个或主要对象。对于每个对象,我将搜索 Map 结构并在给定第一个对象的完全限定名称的情况下找到相应的关联第二个对象。在此之后我只需要实例化第二个对象:
Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });
或
Class<?> clazz = Class.forName(whichClass);
Object object = clazz.newInstance();
如果需要,也可以将对象转换为相应的 Class。
这将使您能够使映射远离代码(在配置文件中简单定义),并且可以在需要时轻松更改。
问题 Creating an instance using the class name and calling constructor 读起来可能很有趣。
P.S.: 我假设示例是 Java 但我想这也可以用其他 OO 语言来完成。
感谢您提供详细信息。这似乎是平行层次结构的情况。您有许多 UI 元素,例如按钮、列表 - 但在绘制这些元素时,您有三个按钮用于三个处理器,三个 TextAreas 用于三个处理器,等等。
如评论中所述,我建议实施桥接模式,其中可以抽象出特定于不同处理器的事物。 ProcessorRenderer(下图)是抽象出来的东西,可以被UI层使用。
另一种类似的方法是使用应用程序外观层。正如您在编辑中提到的,您需要将处理器层次结构与 UI 层分开。我也同意这一点。我不希望 UI 层知道有关处理器的任何信息(或来自域层的任何信息)。 UI 层应该是哑的,它应该只绘制按钮、列表、单选按钮等东西。所以我建议引入一个 Application Facade 层,它会从域层了解处理器层次结构,并且会知道 UI 层中不同类型的 UI 元素,但不应该知道“如何绘制 UI 元素” -> 那部分应该只有笨蛋才知道 UI 层。 UI 层是可测试的,与域无关,而域对 UI 一无所知。 Application Facade层包含的是将Domain层对象转换为UI层可以使用的数据结构。您可以在此处阅读有关应用程序外观的更多信息:https://www.martinfowler.com/apsupp/appfacades.pdf
桥梁模式:https://en.wikipedia.org/wiki/Bridge_pattern
我在这里将 Application Facade 视为 Bridge 模式的一个特例,除了 Application Facade (ProcessorRenderer) 依赖于 UI 层,而在 Bridge 模式中依赖是相反的.但这只是我的意见。
我在这里驳回了使用访问者模式的想法,因为您在编辑中提到您希望将 UI 层与处理器层次结构完全分离。也因为如果在层次结构中所做的一切都是渲染,那么只有一个 Visitor 的实现,即 RenderingVisitor。那完全没问题,但我认为让它成为访客就太过分了。但是,如果您在不同类型的处理器上有许多这样的不同操作,其中每种处理器的每个操作都不同,那么我建议改用访问者模式。 :)