Eliminate Repetitive Java Code: Design Patterns, Annotations & Mapping Tricks
This article explains why duplicate code harms maintainability and demonstrates three practical techniques—factory/template method patterns, annotation‑driven reflection, and bean‑mapping utilities—to refactor Java backend services and dramatically reduce redundant implementations.
Software engineers differ from "code monkeys" by actively removing redundant code using design patterns, OOP, and advanced Java features, which improves the maintainability of large projects.
Business developers often claim that their code lacks technical depth, but design patterns, reflection, and generic utilities provide systematic ways to handle complex logic without duplication.
Maintainability is a key indicator of project maturity; reducing duplicate code is essential because duplicated implementations easily lead to bugs when only one copy is updated.
If identical code exists in multiple places, a change in one place may be missed in others, causing bugs.
Similar code with minor differences can be mistakenly edited together, introducing errors.
Below are three common scenarios and how to eliminate the repetition.
1. Use Factory + Template Method to Remove if…else and Duplicate Logic
We model a shopping‑cart service for three user types (normal, VIP, internal). The initial implementation repeats about 70% of the code across three classes.
public class Cart { private List<Item> items = new ArrayList<>(); private BigDecimal totalDiscount; private BigDecimal totalItemPrice; private BigDecimal totalDeliveryPrice; private BigDecimal payPrice; } public class Item { private long id; private int quantity; private BigDecimal price; private BigDecimal couponPrice; private BigDecimal deliveryPrice; }After extracting the common workflow into an abstract class AbstractCart, the subclasses only implement the variable parts:
public abstract class AbstractCart { public Cart process(long userId, Map<Long, Integer> items) { /* common logic */ for (Item item : itemList) { processCouponPrice(userId, item); processDeliveryPrice(userId, item); } /* calculate totals */ } protected abstract void processCouponPrice(long userId, Item item); protected abstract void processDeliveryPrice(long userId, Item item); }NormalUserCart implements zero discount and 10% delivery fee, VipUserCart overrides the discount logic, and InternalUserCart sets both to zero. Spring bean naming ( @Service("NormalUserCart") etc.) together with applicationContext.getBean(userCategory + "UserCart") forms a simple factory that returns the appropriate cart without additional if statements.
2. Use Annotations + Reflection to Eliminate Repetitive Parameter Handling
Bank APIs require fixed‑length strings, specific padding, and an MD5 signature. A naïve implementation repeats formatting, padding, and signing code for each endpoint.
public static String createUser(String name, String identity, String mobile, int age) throws IOException { StringBuilder sb = new StringBuilder(); sb.append(String.format("%-10s", name).replace(' ', '_')); /* ... */ sb.append(DigestUtils.md2Hex(sb.toString())); return Request.Post("http://localhost:45678/reflection/bank/createUser").bodyString(sb.toString(), ContentType.APPLICATION_JSON).execute().returnContent().asString(); }By defining a class‑level annotation @BankAPI(url="/bank/createUser", desc="Create User") and a field‑level annotation @BankAPIField(order=1, type="S", length=10), we can describe the contract declaratively.
@BankAPI(url="/bank/createUser", desc="Create User") @Data public class CreateUserAPI { @BankAPIField(order=1, type="S", length=10) private String name; @BankAPIField(order=2, type="S", length=18) private String identity; @BankAPIField(order=3, type="N", length=5) private int age; @BankAPIField(order=4, type="S", length=11) private String mobile; }The generic remoteCall(AbstractAPI api) method uses reflection to read the annotations, sort fields by order, apply the correct padding ( S left‑pad with '_' , N left‑pad with '0', M for monetary values), append the MD5 signature, and finally send the request.
private static String remoteCall(AbstractAPI api) throws IOException { BankAPI meta = api.getClass().getAnnotation(BankAPI.class); StringBuilder sb = new StringBuilder(); Arrays.stream(api.getClass().getDeclaredFields()) .filter(f -> f.isAnnotationPresent(BankAPIField.class)) .sorted(Comparator.comparingInt(f -> f.getAnnotation(BankAPIField.class).order())) .peek(f -> f.setAccessible(true)) .forEach(f -> { BankAPIField af = f.getAnnotation(BankAPIField.class); Object value = null; try { value = f.get(api); } catch (IllegalAccessException e) { e.printStackTrace(); } switch (af.type()) { case "S": sb.append(String.format("%-" + af.length() + "s", value.toString()).replace(' ', '_')); break; case "N": sb.append(String.format("%" + af.length() + "s", value.toString()).replace(' ', '0')); break; case "M": if (!(value instanceof BigDecimal)) throw new RuntimeException("BigDecimal expected"); sb.append(String.format("%0" + af.length() + "d", ((BigDecimal) value).setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue())); break; } }); sb.append(DigestUtils.md2Hex(sb.toString())); String param = sb.toString(); return Request.Post("http://localhost:45678/reflection" + meta.url()) .bodyString(param, ContentType.APPLICATION_JSON) .execute().returnContent().asString(); }Service methods now only populate the POJO and call remoteCall, removing all duplicated formatting logic.
3. Use Property‑Copy Tools to Remove Manual DTO/DO Mapping
Manually copying dozens of fields between DTO, DO, and VO objects is error‑prone; the example shows swapped fields, duplicated assignments, and even self‑assignment.
ComplicatedOrderDTO dto = new ComplicatedOrderDTO(); ComplicatedOrderDO d = new ComplicatedOrderDO(); d.setAcceptDate(dto.getAcceptDate()); d.setAddress(dto.getAddress()); /* many more */Switching to a mapping utility such as BeanUtils.copyProperties(dto, d, "id") copies matching properties automatically while allowing an ignore list, dramatically reducing the risk of human error.
In summary, the three kinds of code duplication can be tackled respectively by extracting common logic into abstract classes (template method), describing variable rules with annotations and handling them via reflection, and delegating bulk property copying to a dedicated mapping library.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
