Backend Development 13 min read

System Reconstruction of a Reservation Service: Design Patterns, Business Abstraction, and Deployment Strategies

This article describes the reconstruction of an order‑reservation‑refund system, detailing business background, abstraction of reservation flows, layered business classification, validation stack implementation, unified data models, mechanism‑strategy separation, and step‑by‑step deployment practices for a robust backend service.

Architect
Architect
Architect
System Reconstruction of a Reservation Service: Design Patterns, Business Abstraction, and Deployment Strategies

The article revisits a previous discussion on service‑design‑pattern practices and explains how evolving business requirements demand more extensible and abstracted service architectures, especially for order, reservation, and refund systems that are tightly coupled with user transactions.

1. Project Business Background

The refactoring targets three services: order service (creation, state transition, payment), reservation system (supporting multiple reservation modes such as inventory, merchant‑accept, in‑service customer support, and direct merchant connection), and refund service (handling user, system, merchant, and customer‑service refunds with various rules).

The focus is on the reservation system because its redesign also covers techniques used for the order and refund services.

Goals

Abstract the reservation process and make it template‑driven.

Make the variable parts configurable.

Support seamless switching between old and new flows during rollout.

2. Business Abstraction

The reservation workflow is complex: an order may traverse different channels, and failures in one channel trigger fallback to another. Additional actions such as SMS notifications occur on success or failure, and data validation precedes the reservation.

From these observations the following abstractions are defined:

Primary business (Level‑1): the main reservation flow from start to success/failure, consisting of critical business nodes.

Reservation channels (e.g., inventory, merchant‑accept, customer‑service, direct merchant) represent different modes; transitions between channels are called channel flow.

Channel‑specific operations that affect the primary flow are classified as Level‑2 business.

Post‑process actions that do not affect the core flow (e.g., sending SMS, logging) are Level‑3 business.

3. Refactoring

3.1 Core Business Process

The core (Level‑1) process is modeled as a template engine where each node is an interchangeable interface, allowing configuration without code changes.

Example code for the reservation entry point:

public class KtvReserveService {
    public KtvReserveResultDTO reserve(KtvReserveContext reserveContext) throws ReserveException {
        // validation
        KtvValidateResult validateResult = this.ktvReserveValidateStack.validate(reserveContext);
        if (validateResult == null || !validateResult.isValid()) {
            return KtvReserveResultDTO.createFailedResult("validate invalid");
        }
        // decide channel
        KtvReserveChannel reserveChannel = reserveChannelJudgeService.judgeChannelType(reserveContext);
        reserveDataService.store();
        reserveDataService.transferReserveChannelStatus();
        // start channel reservation
        ChannelResult channelResult = this.reserveChannelService.reserve(reserveContext);
        return KtvReserveResultDTO.genResult(channelResult.isSuccess(), channelResult.getDesc(), reserveFlow.getReserveId());
    }
}

Channel feedback handling:

public class KtvReplyReserveService {
    @Override
    public ReplyReserveResult reply(KtvReplyReserveInfo replyReserveInfo) throws ReplyReserveException {
        // validation
        KtvValidateResult validateResult = replyReserveValidateStack.validate(replyReserveInfo);
        if (validateResult == null || !validateResult.isValid()) {
            logger.warn(String.format(" %s validate failed", param));
            return ReplyReserveResult.createFailedResult("validate failed");
        }
        // update status
        reserveDataService.transferReserveChannelStatus();
        // decide result
        KtvReserveStatus toReserveStatus = this.reserveChannelJudgeService.judgeReserveResult(replyReserveInfo);
        boolean reserveFailed = toReserveStatus == null || toReserveStatus == KtvReserveStatus.ReserveFailed || toReserveStatus == KtvReserveStatus.Init;
        ReplyReserveResult result;
        if (reserveFailed) {
            result = this.reserveFailed(replyReserveInfo);
        } else if (toReserveStatus == KtvReserveStatus.ReserveSuccess) {
            result = this.reserveSuccess(replyReserveInfo);
        } else {
            result = ktvReserveTransferService.transferChannel(ktvReserveContext);
        }
        // channel internal processing
        this.replyReserveChannelService.reply(replyReserveInfo);
        return result;
    }
}

3.2 Validation Stack

Complex pre‑business validation is extracted into a validation stack built with the Chain of Responsibility pattern, assembled separately via a Proxy pattern to keep the main flow clean.

public interface KtvReserveValidateService {
    /** Validate reservation information */
    KtvValidateResult validate(KtvReserveContext reserveContext);
}
public class KtvReserveValidateStack implements KtvReserveValidateService {
    private List
validateServices;
    public void setValidateServices(List
validateServices) {
        this.validateServices = validateServices;
    }
    @Override
    public KtvValidateResult validate(KtvReserveContext reserveContext) {
        if (CollectionUtils.isEmpty(validateServices)) return KtvValidateResult.validResut();
        for (KtvReserveValidateService service : validateServices) {
            KtvValidateResult result = service.validate(reserveContext);
            if (result == null || !result.isValid()) return result;
        }
        return KtvValidateResult.validResut();
    }
}

3.3 Business Layering

Level‑1 business steps must be strictly reliable; failures abort the transaction. Level‑2 business is important but should not affect the final outcome; errors trigger alerts or asynchronous compensation. Level‑3 business is completely decoupled and can be executed asynchronously (e.g., SMS notifications) using the Observer pattern.

3.4 Unified Data Model

A single data contract (e.g., ReserveContext ) is used throughout the flow, preventing duplicated reads and simplifying state management.

3.5 Mechanism‑Strategy Separation

Following the classic Unix principle, core algorithms (mechanism) are separated from interfaces (strategy). This mirrors the MVC pattern and allows independent evolution of strategies such as how reservation results are reported without touching the engine.

4. Deployment Strategy

Two refactoring approaches are discussed: internal logic changes without new tables (easy rollout) and interface changes with new tables (requires compatibility handling). The article recommends incremental, step‑by‑step releases, validating each piece before proceeding.

5. Summary

Key principles applied during the reconstruction include mechanism‑strategy separation, unified protocol design, and the Open‑Closed principle. The design patterns employed are Proxy, Observer, Chain of Responsibility, and Decorator.

Design Patternsservice architecturereservation systembackend refactoringdeployment strategyvalidation stack
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.