添加功能:子类与装饰器

发布于 2024-08-03 02:53:11 字数 786 浏览 2 评论 0原文

我目前正在开发一个遗留系统,使用 Oracle 的 ADF Faces JSF 实现来实现表示层。该系统依靠规则引擎来根据用户与表单元素的交互或输入的值来使某些表单元素成为必需、禁用甚至突出显示。

在当前阶段,该应用程序可以说是“正在运行”。当前处理规则引擎和前端更新的实现不是很优雅,并且由大量 if 语句组成,类似于:

if(screenObj instanceof CoreInputText) {
    ((CoreInputText) screenObj).setDisabled(true);
}

为了使混合复杂化,我们还混合了自己的对象,因此整个集合不会共享一个共同的祖先,因此消除了我们做类似事情的选择:

((CommonAncestor) screenObj).setDisabled(true);

问题是是否值得重新编写这部分代码以使其更加干净和清晰。由于大多数屏幕元素都是 ADF Faces 元素,因此我们无法/不允许更改其祖先以添加其他方法。

代码更改的目标有两个:清理旧代码并改进代码库,以便添加新元素或控件不会导致大量代码更改(特别是对于存在于许多地方的 if 语句) 。

那么,如果我们继续进行这一改变,哪一个是实现我们所寻求的目标的更好选择呢?子类化所有元素(每次我们使用另一个预先存在的控件时都需要一个新类)或实现装饰器模式?我对装饰器唯一关心的是它仍然需要为每个附加元素更改代码。这两个选项似乎都会减少代码更改,因为包含这些 if 块的多个方法不需要更新。

欢迎对除子类化和装饰器之外的处理此类情况的方法提出任何意见!

I'm currently working on a legacy system using Oracle's ADF Faces JSF implementation for the presentation layer. The system relies on a rules engine to make certain form elements required, disabled, or even highlighted depending on the user's interaction with them or values entered.

At it's current stage the application is "working", sort of. The current implementation handling the rules engine and the front end updates isn't very elegant and consists of a large set of if statements similar to:

if(screenObj instanceof CoreInputText) {
    ((CoreInputText) screenObj).setDisabled(true);
}

To complicate the mix we also have our own objects mixed in so the set as a whole does not share a common ancestor thus eliminating our option of doing something like:

((CommonAncestor) screenObj).setDisabled(true);

The question is whether or not it would be worth reworking this portion of the code to be cleaner and clearer. Because the majority of the screen elements are ADF Faces elements we're not able/allowed to change their ancestry to add additional methods.

The goal of the code change would be two fold: clean up older code and improve the code base so that the addition of new elements or controls won't result in a large code change (specifically to the if statements which exist in numerous places).

So if we go forward with this change which would be the better choice of achieving what we're looking for? Subclassing all of the elements (requiring a new class each time we utilize another pre-existing control) or implementing the decorator pattern? My only concern with the decorator is that it would still require a code change for each additional element. Both options would appear to reduce the code changes since multiple methods containing these if blocks wouldn't need updating.

Any input on methods for handling such situations beyond subclassing and decorators is welcome!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美胚控场 2024-08-10 02:53:11

尽管它们没有共同的祖先,但您没有指定它们是否有共同的方法。如果他们这样做,那么也许只需在运行时使用仅调用该方法的代理放入一个接口,这样您就有了一种通用类型。当然,这是一种装饰器,并且由于它使用反射,所以可能太慢(尽管可能不会),但它的优点是任何新对象只需实现正确的方法签名(或者可能让新对象只需实现接口,并为旧对象保留代理,并在工厂方法中有条件地创建代理来检查对象是否需要它)。

另外,如果这是一个真正的设置器,您可以使用 apache 中的 BeanUtils 并将其设置为名为“disabled”的属性。

编辑:鉴于它们没有相同的方法,每次添加新对象时都必须添加一些代码,除非您至少可以控制未来的新对象将具有定义的接口。话虽这么说,如果您愿意沿着反射路线走下去,您可以创建类到方法的映射(假设所有方法都采用布尔值 - 如果需要,您甚至可以强制绕过它)并查找对象在地图中。这样,当您引入新对象时,您只需在映射中添加一个条目。

然而,我的偏好是避免这种情况,因为这似乎让反思太过分了。它使得方法名称很难重构,并且 IDE 无法确定它们是在该上下文中使用的。我认为装饰器乍一看是正确的选择,因为在没有任何其他考虑的情况下,组合应该优于继承,并且它将为正在发生的事情提供更清晰的代码路径,从长远来看改善维护。

Although they don't have a common ancestor, you don't specify if they have a common method. If they do, then perhaps just put in an interface at runtime using a Proxy that just invokes the method so you have one common type. This is a kind of decorator, certainly, and since it uses reflection it may be too slow (although likely not) but it has the advantage of any new objects just having to implement the right method signature (or perhaps have new objects just implement the interface, and reserve the Proxy for old objects and conditionally create the proxy in a factory method that checks if the object needs it).

Also, if this is a true setter, you could use BeanUtils from apache and just set it as a property called disabled.

EDIT: Given that they don't have the same method, some code is going to have to be added every time you add a new object, unless you can at least control that going forward new objects will have a defined interface. That being said, if you are comfortable going down the reflection route, you could create a map of classes to methods (provided the methods all take a boolean - and you could even force your way around that if you have to) and lookup the object in the map. That way when you introduce a new object you only need to add an entry in the map.

However, my preference would be to avoid that, as that seems to take reflection too far. It makes the method names very hard to refactor, and impossible for an IDE to figure out that they are used in that context. I think the decorator is the right choice at first blush because, in the abscense of any other consideration, composition should be prefered to inheritance and it will make a clearer code path as to what is happening, improving maintenance in the long run.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文