To avoid code duplication I come up with the following solution (the common logic might be more complicated, I simplified it for the sake of brevity):
interface Mapper { void saveOne(Map<String, Object> params); void saveTwo(Map<String, Object> params); } public class Main { private static final Mapper mapper = new MapperImpl(); public static void main(String[] args) { saveOne(); saveTwo(); } private static void saveOne() { save(new HashMap<>(Map.of("num", "one")), mapper::saveOne); } private static void saveTwo() { save(new HashMap<>(Map.of("num", "two")), mapper::saveTwo); } private static void save(Map<String, Object> params, Consumer<Map<String, Object>> consumer) { params.put("name", "Some Name"); params.put("type", "Some Type"); consumer.accept(params); } } class MapperImpl implements Mapper { @Override public void saveOne(Map<String, Object> params) { System.out.println("Saving one with params: " + params); } @Override public void saveTwo(Map<String, Object> params) { System.out.println("Saving two with params: " + params); } }
Is the above approach viable, readable, and clean?
Or, it will be better to rewrite it without lambdas and method references:
public static void main(String[] args) { saveOne(); saveTwo(); } private static void saveOne() { Map<String, Object> params = new HashMap<>(); params.put("num", "one"); params.put("name", "Name 1"); params.put("type", "Type 1"); mapper.saveOne(params); } private static void saveTwo() { Map<String, Object> params = new HashMap<>(); params.put("num", "two"); params.put("name", "Name 2"); params.put("type", "Type 2"); mapper.saveTwo(params); }
Which one is better in terms of functionality, purity, and readability?