[JAVA] Important design patterns to improve maintainability

Introduction

Hello. It's Kecho. Have you made code that is not maintainable? Here's the code I've pointed out earlier and improved.

Before improvement

code

public class Main {
	public static void main(String[] args) throws Exception {
		if (args[0].equals(ExecPattern.A.toString())) {
			exeA(args[1]);
		} else if (args[0].equals(ExecPattern.B.toString())) {
			exeB(args[1]);
		} else {
			throw new Exception("illigal request parameter");
		}
	}

	private static void exeA(String input) {
		// something
	}

	private static void exeB(String input) {
		// something
	}
}
public enum ExecPattern {
	A, B
}

Contents

The process is branched by the IF statement using the first argument passed at the time of execution. Actually, I prepared a logic class and went out for the logic part.

What's wrong

In this case, it is necessary to add a new IF statement when the execution pattern C is newly added. It's not maintainable, and frequent controller class updates aren't very desirable. Ideally, any additional modifications should be minimized.

After improvement

code

abstract class ExecLogic {
	abstract void execute(String args);
}

An abstract class inherited by the Logic class. In this case, A class and B class inherit.

public class A extends ExecLogic {
	@Override
	void execute(String args) {
		// something
	}
}
public class B extends ExecLogic {
	@Override
	void execute(String args) {
		// something
	}
}

Logic is described in A and B classes.

public class Main {
	public static void main(String[] args) throws Exception {
		ExecLogic logic = (ExecLogic) Class.forName(args[0]).getDeclaredConstructor().newInstance(); //※1
		logic.execute(args[1]);
	}
}

In the Main class, A and B class instances are created from the runtime arguments and processing is executed.

Class.forName("className").getDeclaredConstructor().newInstance()Let's use.


 Reference: https://qiita.com/deaf_tadashi/items/3c3118e660861fb43434

## What has improved
 Consider actually adding a C class.
 All you have to do is add a C class and write the logic inside.
 No modification is required for the controller class.
 We have now achieved a minimum of modifications when adding.

# bonus
 In reality, I think you'll need to validate the runtime arguments.
 Therefore, it is necessary to avoid increasing the number of corrections.
 Let's implement it as follows.

```java
	private static boolean validate(String[] args) {
		boolean res = false;
		for (ExecPattern execPattern : ExecPattern.values()) {
			if (execPattern.toString().equals(args[0])) {
				res = true;
			}
		}
		return res;
	}

Recommended Posts

Important design patterns to improve maintainability
Introduction to design patterns (introduction)
Introduction to Design Patterns (Builder)
Introduction to Design Patterns (Composite)
Introduction to design patterns (Flyweight)
Introduction to design patterns Prototype
Introduction to Design Patterns (Iterator)
Introduction to Design Patterns (Strategy)
Introduction to Design Patterns (Factory Method)
Introduction to Design Patterns (Abstract Factory)
Various design patterns
Java Design Patterns
Study GoF design patterns
Read design patterns in Ruby
Why design patterns are needed
[Java] Summary of design patterns
Design patterns to try with Swift-Iterator patterns that support Arrays and Dictionary
Design patterns to enjoy with frequently used Java libraries --Factory pattern
I read "7 Design Patterns to Refactor MVC Components in Rails" (writing)