Can anyone recommend a java 8 template to replace a switch statement?

I have the following code:

public class A { private String type; String getType() { return type;} } 

Now in many code places I have code like this

  switch (a.geType()) { case "A" : return new Bla(); case "B" : return new Cop(); } 

or somewhere else

 switch (a.geType()) { case "A" : return new Coda(); case "B" : return new Man(); } 

(Note that I know that I should use Enumeration in production code).

What I want to achieve is that when a new class is added to class A, should the compiler mark all switch statements that need to be adjusted?

Is there an idiomatic java way for this?

+5
source share
4 answers

when a new type is added to class A , should the compiler mark all switch that need to be adjusted?

A good approach to this would be to replace switch with a more robust implementation of multiple sending, such as the Visitor Template :

 interface VisitorOfA { Object visitA(A a); Object visitB(B b); } class A { Object accept(VisitorOfA visitor) { return visitor.visitA(this); } } class B extends A { Object accept(VisitorOfA visitor) { return visitor.visitB(this); } } 

Using this infrastructure, you can remove your switch by replacing them with a visitor implementation:

 Object res = a.accept(new VisitorOfA() { public Object visitA(A a) { return new Bla(); } public Object visitB(B b) { return new Cop(); } }); 

When you add a new subtype to A , say class C , all you have to do is add a new method to VisitorOfA :

 Object visitC(C c); 

Now the compiler will detect all the places where this new method has not been implemented, which avoids run-time problems.

+11
source

Do not forget about good old-fashioned polymorphism. Having a type field with switch statements in a class is often a smell that indicates that a subclass may be useful. Consider:

 public abstract class CommonSuperClass { public abstract One getOne(); public abstract Two getTwo(); } public class A extends CommonSuperClass { @Override public One getOne() { return new Bla(); } @Override public Two getTwo() { return new Coda(); } } public class B extends CommonSuperClass { @Override public One getOne() { return new Cop(); } @Override public Two getTwo() { return new Man(); } } 

If you must add a new subclass of C, you need to provide implementations of abstract methods (unless you make C itself abstract).

+7
source

You may have a line / provider map:

 Map<String, Supplier<Object>> map = new HAshMap<> (); map.put("A", Bla::new); map.put("B", Cop::new); 

And your sample code would look like this:

 return map.get(a.getType()).get(); //need null check 
+2
source

In the perspective of abstraction, there is another approach to use. One way is polymorphism, as shown here .

A simple example:

 public void EverythingYouWant (Animal animal) { return animal.move(); } 

When it comes to refactoring, replace type code / validation with State / Strategy templates . It is a good solution to first consider if there is any reason that prevents the subclass.

0
source

Source: https://habr.com/ru/post/1202695/


All Articles