如何使用Java的功能应用干燥原理?
在JSF应用程序中,我有一些具有多个返回点的方法,如下:
public String Method1() {
...
if (condition1) {
elaborate1();
return "Case1";
}
if (condition2) {
elaborate2();
return "Case2";
}
if (condition3) {
elaborate3();
return "Case3";
}
...
}
更多的方法和随之而来的阐述是更多方法,我只想写一次。不幸的是,由于多个返回点,重构并不容易。
我对功能接口不满意,但我希望可以使用它们来重构上述代码。我的想法是写这样的东西:
String elaboration1 ( T NextElaborations) {
if (condition1) {
elaborate1();
return "Case1";
}
return NextElaborations.get();
}
有可能吗?我被困住了,大多数互联网上的示例都使用lambdas而不是方法。
更新1 @Alexander Ivanchenko 在评估答案之前,我需要研究您提供的链接,我对流不熟悉。
在发布问题后,我通过功能性接口进行了一些练习,最终得到了以下伪Java代码:
@FunctionalInterface
public interface MethodComposition {
String Execute(Supplier<String> supplier)
}
...
String FinalStep() {
FinalElaboration();
return "finalResult";
}
String ElaborationX(Supplier<String> supplier) {
if (conditionX) {
elaborationX();
return "ResultX";
}
return supplier.get();
}
...
public String Method1() {
Supplier<String> finalSupplier = this::FinalStep;
MethodComposition stepX = this::ElaborationX;
...
return step1.Execute(() ->
step2.Execute(() ->
...
stepN.Execute(finalSupplier)));
}
尽管语法丑陋,但它非常接近我想要的,我需要更加灵活性,因为 elaborationx() 在 Method1 和 Method_n 中是非常相似的,但不相等。
In a JSF application I have some methods with multiple return points as the following:
public String Method1() {
...
if (condition1) {
elaborate1();
return "Case1";
}
if (condition2) {
elaborate2();
return "Case2";
}
if (condition3) {
elaborate3();
return "Case3";
}
...
}
The conditions and consequent elaborations are common to more methods, and I would like to write them only once. Unfortunately, it is not easy to refactor due to the multiple return points.
I'm not comfortable with functional interfaces, but I hope I could use them to refactor the code above. My idea is to write something like this:
String elaboration1 ( T NextElaborations) {
if (condition1) {
elaborate1();
return "Case1";
}
return NextElaborations.get();
}
Is it possible ? I'm stuck, most examples on internet use lambdas and not methods.
Update 1
@Alexander Ivanchenko
I need to study the links you provided before evaluating your answer, I'm not familiar with streams.
After posting the question I made some practice with Functional interfaces and ended up with the following pseudo java code:
@FunctionalInterface
public interface MethodComposition {
String Execute(Supplier<String> supplier)
}
...
String FinalStep() {
FinalElaboration();
return "finalResult";
}
String ElaborationX(Supplier<String> supplier) {
if (conditionX) {
elaborationX();
return "ResultX";
}
return supplier.get();
}
...
public String Method1() {
Supplier<String> finalSupplier = this::FinalStep;
MethodComposition stepX = this::ElaborationX;
...
return step1.Execute(() ->
step2.Execute(() ->
...
stepN.Execute(finalSupplier)));
}
Despite the ugly syntax it is quite close to what I wanted, I would need more flexibility because ElaborationX() is very similar but not equal in Method1 and Method_N.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以定义函数的A 集合 表示这些条件,并通过提供便捷的与之交互的方式将此集合封装在类中。这将使此逻辑可重复使用。
例如,您可以创建一个关联的 map /util/function/predicate.html“ rel =” nofollow noreferrer“>
predicate
,它是代表解决条件的 function 布尔值
值,具有特定的返回 value 。收集应具有可预测的迭代顺序,以确保应用条件的顺序,因此您可以使用linkedhashmap
强加迭代顺序。您可以通过将单独的条件表示为对象,并包含谓词一些附加属性来实现更大的灵活性。这将允许对条件进行分类并构建谓词的不同组合。
您的方法
method1()
用链条的链条 - 可以用地图条目来替换。或者,如果您对流感到不舒服,则可以使用 loop的普通代替它。关键点是,您需要均值对函数的集合进行迭代。
无需产生许多方法,例如
elaboration1()
,eLaboration2()
等。而且,这种方法与Java中的功能接口(您已经提到的)和功能方法编程一般都无关。在想重构您的代码阶层功能上,除了真正熟悉功能编程外,别无他法。我鼓励您在 lambda表达 和
<
流逻辑的描述:
true
确定条目。可选
的对象(如果找到结果,将是空)来终止流管线的对象,通过应用“操作findfirst()
”。实现可能看起来像这样:
main()
You can define a collection of functions representing these conditions and encapsulate this collection inside a class by providing convenient ways of interacting with it. That will make this logic reusable.
For example, you can create a map that associates a
Predicate
, which is a function that represents a condition that resolves toboolean
value, with a particular return value. Collection should have a predictable order of iteration to insure the order in which conditions will be applied, therefore you can useLinkedHashMap
to impose the order of iteration.And you can achieve more flexibility by representing a separate condition as an object, containing a predicate some additional attributes. That will allow to categorize conditions and construct different combinations of predicates.
Your method
Method1()
with a chain ofif
-statements can be substituted with a stream of map entries. Or if you fill uncomfortable with streams, you might use a plainfor
-loop in place of it. The key point is that you need a mean to perform the iteration over the collection of functions.No need to spawn a number of methods like
elaboration1()
,elaboration2()
, etc. that depend on one another, this approach is unflexible. And this approach has nothing to do with functional interfaces in Java (that you've mentioned) and functional approach programming in general. In want to refactor you code to be functional in stile, there's no other way than to actually get familiar with functional programming.I encourage you to have a look at these official tutorials on lambda expressions and
streams.
Description of the stream-logic:
true
.Optional
(which will be empty if no result was found) by applying the operationfindFirst()
.The implementation might look like this:
main()