Java Omnibus
OOAD & Architecture / OOA / OOD process / Refactoring Towards Patterns in Java
OOA/OOD Process Java Order Management
OOA / OOD Process

Most useful patterns are discovered through refactoring pressure, not inserted at the start as decoration.

One of the healthiest ways to arrive at patterns is to refactor toward them. A Java system grows, change pressure reveals repeated variation or awkward responsibilities, and the design moves toward a clearer pattern because the need is now obvious. This produces stronger judgment than applying a pattern by name from day one.

Why This Topic Matters

Why it matters in real Java systems

Order-management systems evolve unevenly. Discounts may remain simple for months, then suddenly multiply. Notifications may start as email only, then expand to SMS, webhooks, and in-app messages. Refactoring toward patterns lets the design grow when real variability or complexity appears.

Core Explanation

The design idea behind this process step

Refactoring toward patterns sits naturally between OOAD principles and the GoF catalog. It teaches you to see why a strategy, factory, observer, or state structure might emerge from the current pain in the code.

In Java, this often means first isolating responsibilities, then extracting stable contracts, then moving conditional logic or object creation into more coherent forms. The pattern becomes the result of good pressure management, not the starting slogan.

This approach usually produces simpler systems because abstractions appear only where change has already justified them.

Concept Breakdown

Key ideas to keep in view

Concept

Smells create pattern pressure

Repeated conditionals, tangled construction, and bloated coordination often hint at a better structure.

Concept

Refactoring preserves working behavior

The path matters: improve design incrementally without betting the whole system on a rewrite.

Concept

Patterns should solve a present problem

A pattern is most useful when you can point to the concrete pressure it relieved.

Java Example

Java example in the Order Management domain

Java example: moving discount conditionals toward strategy
package org.javaomnibus.ecommerce.process;

public interface DiscountPolicy {
    Money apply(Order order, Money subtotal);
}

public final class LoyaltyDiscountPolicy implements DiscountPolicy {
    @Override
    public Money apply(Order order, Money subtotal) {
        return subtotal.multiply(95).divide(100);
    }
}

public final class CheckoutPricingService {
    private final DiscountPolicy discountPolicy;

    public CheckoutPricingService(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
    }

    public Money finalTotal(Order order, Money subtotal) {
        return discountPolicy.apply(order, subtotal);
    }
}
Code Walkthrough

Step by step

  1. The design moved toward strategy because discount variation became real.
  2. CheckoutPricingService now depends on a policy instead of on a growing conditional block.
  3. This is a pattern-shaped result produced by change pressure, not pattern enthusiasm.
  4. The next change point is clearer and more localized.
Real-World Usage

Where this process step shows up in practice

  • Incrementally improving legacy Java services without large rewrites
  • Teaching teams how design principles lead naturally into patterns
  • Making evolving rules easier to extend with tests already in place
Trade-Offs

When to be careful

If you wait too long, the refactoring cost increases. If you abstract too early, the design gains indirection without value. The skill is in spotting the moment variation becomes persistent.

Common Mistakes

Frequent mistakes to watch for

  • Introducing a pattern before the need is visible
  • Calling something a refactoring while changing behavior at the same time
  • Extracting interfaces without a clear source of variation
  • Assuming every smell implies a classic named pattern
Related Pages

Related concepts


What To Read Next