如何使用Java的功能应用干燥原理?

发布于 2025-01-22 20:14:21 字数 1498 浏览 3 评论 0原文

在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 技术交流群。

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

发布评论

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

评论(1

凉薄对峙 2025-01-29 20:14:22

您可以定义函数的A 集合 表示这些条件,并通过提供便捷的与之交互的方式将此集合封装在类中。这将使此逻辑可重复使用。

例如,您可以创建一个关联的 map /util/function/predicate.html“ rel =” nofollow noreferrer“> predicate ,它是代表解决条件的 function 布尔值值,具有特定的返回 value 。收集应具有可预测的迭代顺序,以确保应用条件的顺序,因此您可以使用linkedhashmap强加迭代顺序。

您可以通过将单独的条件表示为对象,并包含谓词一些附加属性来实现更大的灵活性。这将允许对条件进行分类并构建谓词的不同组合。

您的方法method1()用链条的链条 - 可以用地图条目来替换。或者,如果您对流感到不舒服,则可以使用 loop的普通代替它。关键点是,您需要均值对函数的集合进行迭代。

我对功能接口不满意,但是...

我被卡住了,互联网上的大多数示例都使用lambdas而不是方法。

无需产生许多方法,例如elaboration1()eLaboration2()等。而且,这种方法与Java中的功能接口(您已经提到的)和功能方法编程一般都无关。在想重构您的代码阶层功能上,除了真正熟悉功能编程外,别无他法。

我鼓励您在 lambda表达
<

流逻辑的描述:

实现可能看起来像这样:

public class FunctionStorage {
    
    public static final Map<Predicate<String>, String> conditions = new LinkedHashMap<>(); // LinkedHashMap insures the order of iteration
        
    static {
        conditions.put(s -> false, "1");
        conditions.put(s -> true,  "2");
        conditions.put(s -> false, "3");
    }
    
    public static Stream<Map.Entry<Predicate<String>, String>> getConditions() {
        return conditions.entrySet().stream();
    }  
}

main()

public static void main(String[] args) {
    String result = FunctionStorage.getConditions()        // a stream of entries
        .filter(entry -> entry.getKey().test("someValue")) // filtering the entry containing the matching condition
        .findFirst()
        .map(Map.Entry::getValue)                          // extracting the return value
        .orElse("defaultValue"); // orElseThrow() depending on your needs
}

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 to boolean 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 use LinkedHashMap 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 of if-statements can be substituted with a stream of map entries. Or if you fill uncomfortable with streams, you might use a plain for-loop in place of it. The key point is that you need a mean to perform the iteration over the collection of functions.

I'm not comfortable with functional interfaces, but ...

I'm stuck, most examples on internet use lambdas and not methods.

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:

The implementation might look like this:

public class FunctionStorage {
    
    public static final Map<Predicate<String>, String> conditions = new LinkedHashMap<>(); // LinkedHashMap insures the order of iteration
        
    static {
        conditions.put(s -> false, "1");
        conditions.put(s -> true,  "2");
        conditions.put(s -> false, "3");
    }
    
    public static Stream<Map.Entry<Predicate<String>, String>> getConditions() {
        return conditions.entrySet().stream();
    }  
}

main()

public static void main(String[] args) {
    String result = FunctionStorage.getConditions()        // a stream of entries
        .filter(entry -> entry.getKey().test("someValue")) // filtering the entry containing the matching condition
        .findFirst()
        .map(Map.Entry::getValue)                          // extracting the return value
        .orElse("defaultValue"); // orElseThrow() depending on your needs
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文