Java on this page 1.8 It is assembled with.
If you have the following interface
Logic.java
public interface Logic {
public void printSkyColor();
}
It was implemented like this. It feels like calling the implementation class differently.
public void execute(String type) {
Logic logic = null;
if("S".equals(type)){
logic = new SunnyLogic();
}else if("C".equals(type)){
logic = new CloudyLogic();
}else if("R".equals(type)){
logic = new RainyLogic();
}else{
throw new UnsupportedOperationException("unknown type : "+ type);
}
//SunnyLogic -> "It is Blue."Is output as standard
//CloudyLogic-> "It is White."Is output as standard
//RainyLogic-> "It is Gray."Is output as standard
logic.printSkyColor();
}
You can think of this as "enumerating" the logic corresponding to the type, right? Is it a little cleaner if you use enums well?
I thought, and actually tried it.
First, create an enumeration class like this.
LogicConstant.java
public enum LogicConstant {
SUN("S", new SunnyLogic()),
CLOUD("C", new CloudyLogic()),
RAIN("R", new RainyLogic()),
;
private final String type;
private final Logic logic;
private LogicConstant(String type, Logic logic) {
this.type = type;
this.logic = logic;
}
public static Logic ofLogic(String type) {
for(LogicConstant c : values()){
if(c.type.equals(type)){
return c.logic;
}
}
return null;
}
}
The side that uses the above enum looks like this.
public void execute(String type) {
Logic logic = LogicConstant.ofLogic(type);
if(logic == null){
throw new UnsupportedOperationException("unknown type : "+ type);
}
//System.out.print(logic.hashCode()+":");
logic.printSkyColor();
}
It still works, but it works, ** The logic class instance is decisively different from the one before the change. ** ** ** Before the change, an instance is created every time, but after the change, it is the same instance. ** ** That is the point.
As you can see from the source,
//System.out.print(logic.hashCode()+":");
You can check the hash value by uncommenting this comment out on the user side.
Separate instantiation means defining only the class to be generated It's like this because it means new when calling.
LogicConstant.java
public enum LogicConstant {
SUN("S", SunnyLogic.class),
CLOUD("C", CloudyLogic.class),
RAIN("R", RainyLogic.class),
;
private final String type;
private final Class<? extends Logic> logic;
private LogicConstant(String type, Class<? extends Logic> logic) {
this.type = type;
this.logic = logic;
}
public static Logic ofLogic(String type) {
for(LogicFactory c : values()){
if(c.type.equals(type)){
try {
return c.logic.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
return null;
}
}
A little more remodeling from here.
return c.logic.newInstance();
First Class's newInstance () is deprecated in java9
Class getDeclaredConstructor (). newInstance ()
Replace it here as specified in javadoc in java9.
In addition, parameters can be passed at the time of constructor anyway So rewrite it so that the parameters are routed.
Since another instance is created for each call, the class name is also set to Factory.
Finally Fixed to throw an exception instead of returning null. (Thank you for your advice!)
Reflecting this ... This is the finished product.
LogicFactory.java
public enum LogicFactory {
SUN("S", SunnyLogic.class),
CLOUD("C", CloudyLogic.class),
RAIN("R", RainyLogic.class),
;
private final String type;
private final Class<? extends Logic> logic;
private LogicFactory(String type, Class<? extends Logic> logic) {
this.type = type;
this.logic = logic;
}
public static Logic ofLogic(String type, Object... initargs) {
for(LogicFactory c : values()){
if(c.type.equals(type)){
try {
return c.logic.getDeclaredConstructor().newInstance(initargs);
} catch (
InstantiationException | IllegalAccessException | IllegalArgumentException |
InvocationTargetException | NoSuchMethodException | SecurityException e
) {
e.printStackTrace();
throw new IllegalArgumentException("type : "+type, e);
}
}
}
throw new UnsupportedOperationException("unknown type : "+ type);
}
}
Following these corrections The null judgment on the caller side is no longer necessary, so delete it.
Well, this kind of refactoring work is often said to be a hobby. I think that it should be organized as much as possible in consideration of operation and maintenance, and that it should be consciously coded.
Studying or reviewing enums? I will describe it for some time.
Recommended Posts