简体   繁体   English

有没有更好更简洁的方法来编写这两个函数?

[英]Is there a better and cleaner way to write this two functions?

So I am struggling to write this code in a clean way.所以我正在努力以一种干净的方式编写这段代码。 I do not know if there is a better way.不知道有没有更好的办法。

private function1(Collection<D> collection) {
    for (Iterator it = collection.iterator(); it.hasNext(); ) {
        Object object = it.next();
        switch (object .getClass().getSimpleName()) {
            case "A": do some work with class A
                break;
            case "B": do some work with class B
                break; 
            case "C": do some work with class C
                break;  
        }
    }
}

So I get a collection which I iterate.所以我得到了一个我迭代的集合。 But the collection can be three different classes in the collection since class A,B,C are of the parent class D. I think my code is not clean and I am looking for a good way to write this.但是集合可以是集合中的三个不同的类,因为 class A、B、C 是父 class D 的父类。我认为我的代码不干净,我正在寻找一个好方法。 Here is another example that I have which is a bit different.这是我的另一个例子,它有点不同。

private function2(Collection<A,B,C> collection) {
    for (Iterator it = collection.iterator(); it.hasNext(); ) {
        Object object = it.next();
        switch (object .getClass().getSimpleName()) {
            case "A": do some work with class A
                break;
            case "B": do some work with class B
                break; 
            case "C": do some work with class C
                break;  
        }
    }
}

In this function I can get either a collection of class A of class B or of class C. In this function I can get either a collection of class A of class B or of class C. I though about making three separate functions for each class.我想为每个 class 创建三个单独的函数。 But than I would have code duplicates.但比我有代码重复。 But I don't know if it would be actually better to split function2 into function2A, function2B, function2C.但我不知道将function2拆分为function2A,function2B,function2C是否会更好。

Is there a better and cleaner way to implement those two functions.有没有更好更干净的方法来实现这两个功能。 Classes A,B,C and D are from a framework. A、B、C 和 D 类来自一个框架。 So I am unable to edit them.所以我无法编辑它们。

Here is one idea.这是一个想法。 Mainly it separates the list of classes to process from the calling method so you don't have to modify your switch method to add other classes.主要是将要处理的类列表与调用方法分开,因此您不必修改 switch 方法来添加其他类。 Note that Collections implement Iterable so you don't need an explicit iterator.请注意, Collections 实现了Iterable ,因此您不需要显式迭代器。

It also presumes you would have methods established to do the required work.它还假定您已经建立了方法来完成所需的工作。

  • build a map of name to method to call.构建一个名称为 map 的方法来调用。 This part replaces your switch statement.这部分替换了您的 switch 语句。
  • it uses a default method to catch unknown class names should they appear它使用默认方法来捕获未知的 class 名称(如果它们出现)
  • it them simply iterates, processing the objects.他们只是迭代,处理对象。
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class WorkFunction {
    Map<String, Consumer<Object>> fnc = Map.of(
              "A", this::doWorkA,
              "B", this::doWorkB,
              "C", this::doWorkC);
    public static void main(String[] args) {
         WorkFunction wf = new WorkFunction();
         
         List<Object> list = List.of(new A(), new B(), new A(), new A(),
                                     new C(), new B(), wf);
         
         wf.function1(list);
    }
      
    static class A {}
    static class B {}
    static class C {}

        public <D> void function1(Collection<D> collection) {
             for(D object : collection) {
                  fnc.getOrDefault(object.getClass().getSimpleName(), 
                           (ob)->System.out.println("Who are you??")))
                  .accept(object);
               }
         }
        
        public void doWorkA(Object ob) {
            System.out.println("Working on A");
        }
        public void doWorkB(Object ob) {
            System.out.println("Working on B");         
        }
        public void doWorkC(Object ob){
            System.out.println("Working on C");
        }
        
}

prints印刷

Working on A
Working on B
Working on A
Working on A
Working on C
Working on B
Who are you??

You can create an interface that A, B, and C can implement from.您可以创建 A、B 和 C 可以实现的接口。 In your interface you can declare a method that will 'do the work' and A,B, and C can have their own implementations.在您的界面中,您可以声明一个“完成工作”的方法,并且 A、B 和 C 可以有自己的实现。

interface MyInterface{
  void doTheWork();
}

Then do this for each class然后对每个 class 执行此操作

class A implements MyInterface { 
    void doTheWork() { 
        ...
    } 
}

Now you can just loop through the collection without having to check what class the instance is of现在您可以遍历集合,而无需检查实例的 class

EDIT - If you cannot modify A,B, or C than you can use a map with the class as the key and a lambda as the value. EDIT - If you cannot modify A,B, or C than you can use a map with the class as the key and a lambda as the value.

Map<Class,Runnable> lambdaClassMap = new HashMap<>();
lambdaClassMap.put(A.class, () -> doAWork(object));
lambdaClassMap.put(B.class, () -> doBWork(object));
lambdaClassMap.put(C.class, () -> doCWork(object));

//psuedocode
for(...) {
    Object object = it.next();
    lambdaClassMap.get(object.getClass()).run();
}

Utilize polymorphism to avoid the need to determine which subclass it is for the purpose of doing different work for each class.利用多态性避免需要确定它是哪个子类,以便为每个 class 做不同的工作。

Add a method doWork (or whatever name you have that would be more appropriate) to the D superclass, and implement it in all the subclasses A , B , and C .D超类添加一个方法doWork (或任何更合适的名称),并在所有子类ABC中实现它。 It may be abstract in D if appropriate.如果合适,它可以在D中是abstract的。

Then your method becomes the following:然后你的方法变成如下:

private void function1(Collection<? extends D> collection) {
    for (Iterator<? extends D> it = collection.iterator(); it.hasNext(); ) {
        D d = it.next();
        d.doWork();
    }
}

Use ? extends D使用? extends D ? extends D so that the method can accept a Collection<D> , Collection<A> , Collection<B> , or Collection<C> . ? extends D以便该方法可以接受Collection<D>Collection<A>Collection<B>Collection<C> This also avoids the raw Iterator .这也避免了原始的Iterator

You can also use the equivalent, shorter, enhanced for loop:您还可以使用等效的、更短的、增强的 for 循环:

private void function1(Collection<? extends D> collection) {
    for (D d : collection) {
        d.doWork();
    }
}

Your second method appears just like the first method except that it attempts to use a Collection<A, B, C> , which doesn't make sense.您的第二种方法看起来就像第一种方法一样,只是它尝试使用没有意义的Collection<A, B, C> Collection has only one type parameter. Collection只有一个类型参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM