You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

针对不同Sample子类实例调用不同方法的设计模式咨询(Spring MVC)

Great question! This is a classic scenario where you want to keep your DTOs clean (free of business logic) while organizing type-specific behavior in separate components. Let’s break down the best approaches for Java (especially with Spring MVC) and non-Java technologies:

Java + Spring MVC Solutions

1. Visitor Pattern (Perfect for Separation of Concerns)

The Visitor pattern is tailor-made for this situation—it lets you define new operations on your hierarchy of Sample subclasses without modifying the DTOs themselves beyond a tiny hook. Here's how to implement it:

First, define a Visitor interface that declares a method for each subclass:

public interface SampleVisitor {
    void visit(Class1 class1);
    void visit(Class2 class2);
    void visit(Class3 class3);
}

Then, add an accept method to your base Sample class (this is the only change needed in your DTOs, and it's just a routing hook, not business logic):

public abstract class Sample {
    public abstract void accept(SampleVisitor visitor);
}

// For each subclass:
public class Class1 extends Sample {
    @Override
    public void accept(SampleVisitor visitor) {
        visitor.visit(this);
    }
}
// Repeat the accept method for Class2 and Class3

Now, create a concrete visitor that holds your business logic (mark it as a Spring @Component so it's managed by the container):

@Component
public class SampleBusinessVisitor implements SampleVisitor {
    @Override
    public void visit(Class1 class1) {
        // Logic from method1 goes here
        validateClass1Data(class1);
        syncClass1ToDatabase(class1);
    }

    @Override
    public void visit(Class2 class2) {
        // Logic from method2 goes here
        generateClass2Report(class2);
    }

    @Override
    public void visit(Class3 class3) {
        // Logic from method3 goes here
        sendClass3Notification(class3);
    }

    // Helper methods with your business logic
    private void validateClass1Data(Class1 class1) { /* ... */ }
    private void syncClass1ToDatabase(Class1 class1) { /* ... */ }
    // ...
}

In your Spring service/controller, inject the visitor and use it like this:

@Autowired
private SampleBusinessVisitor visitor;

public void processSample(Sample obj) {
    obj.accept(visitor);
}

2. Strategy Pattern + Type Matching (No DTO Modifications)

If you don’t want to add any code to your DTOs at all, this approach is more flexible. Create a handler interface for type-specific processing:

public interface SampleHandler {
    boolean supports(Sample sample);
    void handle(Sample sample);
}

Then create a handler for each subclass (use @Component for Spring management):

@Component
public class Class1Handler implements SampleHandler {
    @Override
    public boolean supports(Sample sample) {
        return sample instanceof Class1;
    }

    @Override
    public void handle(Sample sample) {
        Class1 class1 = (Class1) sample;
        // Logic from method1 goes here
    }
}

// Repeat for Class2Handler and Class3Handler

Create a manager component to resolve the right handler automatically:

@Component
public class SampleHandlerManager {
    private final List<SampleHandler> handlers;

    // Spring injects all SampleHandler beans automatically via constructor
    public SampleHandlerManager(List<SampleHandler> handlers) {
        this.handlers = handlers;
    }

    public void processSample(Sample sample) {
        handlers.stream()
            .filter(handler -> handler.supports(sample))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("No handler found for sample type"))
            .handle(sample);
    }
}

Now you can inject this manager into your controllers/services and process DTOs without touching the original classes.

Non-Java Solutions

If you’re open to other languages, here are some concise alternatives that avoid polluting DTOs:

Kotlin

Kotlin’s when expression with smart casts and extension functions makes this incredibly clean:

// Define extension functions for each subclass (kept separate from DTOs)
fun Class1.process() { /* method1 logic */ }
fun Class2.process() { /* method2 logic */ }
fun Class3.process() { /* method3 logic */ }

// Usage
fun handleSample(obj: Sample) {
    when(obj) {
        is Class1 -> obj.process()
        is Class2 -> obj.process()
        is Class3 -> obj.process()
        else -> throw IllegalArgumentException("Unsupported sample type")
    }
}

Go

Use type assertions with a switch case to route to type-specific functions:

type Sample interface{}
type Class1 struct{}
type Class2 struct{}
type Class3 struct{}

func processClass1(c *Class1) { /* method1 logic */ }
func processClass2(c *Class2) { /* method2 logic */ }
func processClass3(c *Class3) { /* method3 logic */ }

func HandleSample(obj Sample) {
    switch v := obj.(type) {
    case *Class1:
        processClass1(v)
    case *Class2:
        processClass2(v)
    case *Class3:
        processClass3(v)
    default:
        panic("unsupported sample type")
    }
}

Python (3.10+)

Use pattern matching with match statements to handle type-specific logic:

class Sample: pass
class Class1(Sample): pass
class Class2(Sample): pass
class Class3(Sample): pass

def process_sample(obj: Sample):
    match obj:
        case Class1():
            # method1 logic
            print("Processing Class1")
        case Class2():
            # method2 logic
            print("Processing Class2")
        case Class3():
            # method3 logic
            print("Processing Class3")
        case _:
            raise ValueError("Unsupported sample type")

Both the Visitor and Strategy patterns integrate seamlessly with Spring MVC—you can inject the visitor/handler manager into your controllers to process incoming DTOs directly from HTTP requests.

内容的提问来源于stack exchange,提问作者Farrukh Chishti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:37:12