Mastering the Decorator Pattern in Spring Boot: A Multi‑Layered Example

This article explains the Decorator (Wrapper) pattern, shows how to apply it in a Spring Boot project with concrete surfing‑service examples, demonstrates single‑ and multi‑layer decorators, and provides complete Java code and controller snippets to illustrate dynamic behavior extension without modifying existing classes.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Mastering the Decorator Pattern in Spring Boot: A Multi‑Layered Example

Preface

This article introduces how to use the Decorator pattern, often called the Wrapper pattern, in a Spring Boot project through a practical example.

What Is the Decorator Pattern?

Official definition

The Decorator Pattern (also known as the Wrapper Pattern) adds functionality to an object without changing its original structure, offering a more flexible alternative to inheritance for extending object behavior. It belongs to the structural design patterns.

Plain language

It’s like composing: I don’t touch the original business logic, but I want to attach extra responsibilities to it.

Non‑intrusive.

Composable.

Practical Implementation

Scenario Overview

We define an interface ISurfTheInternetService representing an online‑surfing service, and two concrete implementations: FadInternetCafe (stylish internet cafe) and RetroInternetBar (retro internet bar).

/**
 * @Author: JCccc
 * @Date: 2022-10-07 15:18
 * @Description: 网上冲浪
 */
public interface ISurfTheInternetService {
    /**
     * 冲起来
     */
    void doSurfing();
}
import com.example.mydemo.service.ISurfTheInternetService;
import org.springframework.stereotype.Service;

@Service("fadInternetCafeService")
public class FadInternetCafe implements ISurfTheInternetService {
    @Override
    public void doSurfing() {
        System.out.println("在时尚 网咖 ,网上冲浪咯~");
    }
}
import com.example.mydemo.service.ISurfTheInternetService;
import org.springframework.stereotype.Service;

@Service("retroInternetBarService")
public class RetroInternetBar implements ISurfTheInternetService {
    @Override
    public void doSurfing() {
        System.out.println("在复古 网吧 ,网上冲浪咯~");
    }
}

A simple controller method invokes both services to demonstrate the basic behavior:

@Autowired
@Qualifier("fadInternetCafeService")
ISurfTheInternetService fadInternetCafeService;

@Autowired
@Qualifier("retroInternetBarService")
ISurfTheInternetService retroInternetBarService;

@GetMapping("/doTest")
public void doTest() {
    fadInternetCafeService.doSurfing();
    retroInternetBarService.doSurfing();
}

The console output shows each implementation’s message:

Adding a Decorator

We create SurfDecorator that implements the same interface and holds a reference to another ISurfTheInternetService. Its doSurfing method adds extra behavior before delegating to the wrapped service.

public class SurfDecorator implements ISurfTheInternetService {
    /** Internal reference to the original service */
    private ISurfTheInternetService surfTheInternetService;

    public SurfDecorator(ISurfTheInternetService surfTheInternetService) {
        this.surfTheInternetService = surfTheInternetService;
    }

    @Override
    public void doSurfing() {
        System.out.println("SurfDecorator 模拟业务 增强器在玩一点很新的东西,可能是一些额外的职责业务....");
        surfTheInternetService.doSurfing();
        System.out.println("SurfDecorator 模拟业务 增强器在玩一点很新的东西,可能是一些额外的职责业务,比如说是XXXX");
    }
}

Controller usage:

@GetMapping("/useDecoratorTest")
public void useDecoratorTest() {
    SurfDecorator fadInternetCafeDecoratorService = new SurfDecorator(fadInternetCafeService);
    fadInternetCafeDecoratorService.doSurfing();

    SurfDecorator retroInternetBarDecoratorService = new SurfDecorator(retroInternetBarService);
    retroInternetBarDecoratorService.doSurfing();
}

Multi‑Layer Decoration

Sometimes a single decorator is not enough. We create RechargeDecorator that extends SurfDecorator and adds a recharge‑checking step.

public class RechargeDecorator extends SurfDecorator {
    public RechargeDecorator(ISurfTheInternetService surfTheInternetService) {
        super(surfTheInternetService);
    }

    @Override
    public void doSurfing() {
        super.doSurfing();
        checkRecharge();
    }

    private void checkRecharge() {
        System.out.print("RechargeDecorator 也在增强,看看这个货卡里面充了有多少,就来上网");
    }
}

Controller method demonstrating two‑level decoration:

@GetMapping("/moreDecoratorTest")
public void moreDecoratorTest() {
    // First layer
    SurfDecorator retroInternetBarDecoratorService = new SurfDecorator(retroInternetBarService);
    // Second layer
    RechargeDecorator rechargeDecorator = new RechargeDecorator(retroInternetBarDecoratorService);
    rechargeDecorator.doSurfing();
}

Through these examples we see how the Decorator pattern enables dynamic, non‑intrusive extension of business logic, and how multiple decorators can be stacked to compose complex behavior in a Spring Boot application.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaBackend DevelopmentSpring BootDecorator Pattern
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

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.