表单编号Switch语句重复代码重构方案咨询——初级开发者代码优化需求
Hey there! Let's tackle this refactoring step by step—your code has a classic opportunity to become cleaner and more maintainable, so let's break it down.
First: Eliminating Duplicate Case Calls
The biggest pain point here is those repeated cases pointing to the same method. Instead of a switch block, we can use a lookup map to directly associate form numbers with their corresponding handlers. This completely removes redundant code and makes updates far easier later on.
First, let's fix the parameter inconsistency (your G642/G979 cases use different parameters) by wrapping all required data into a single context object. This keeps handler signatures consistent and avoids messy, long parameter lists:
// Context class to hold all shared parameters class FormProcessingContext { private final Account account; private final State state; private final Form form; private final BusinessDealing businessDealing; private final Period period; private final WcmJurisdiction wcmJurisdiction; private final Form newForm; private final WcmBusiness wcmBusiness; private final Form frm; // Constructor and getters for all fields }
Next, create a map that links form numbers to their handling logic:
// Map form numbers to their respective handler functions private static final Map<String, Consumer<FormProcessingContext>> FORM_HANDLERS = Map.of( "A1345", ctx -> getExclusionDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "B254", ctx -> getExclusionDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "B297", ctx -> getPartnershipDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "C397", ctx -> getBrokerageDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "D972", ctx -> getBrokerageDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "E192", ctx -> getBrokerageDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "E299", ctx -> getBrokerageDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "F254", ctx -> getLocationDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "F795", ctx -> getLocationDetails(ctx.getAccount(), ctx.getState(), ctx.getForm(), ctx.getBusinessDealing()), "G642", ctx -> getContractDetails(ctx.getPeriod(), ctx.getWcmJurisdiction(), ctx.getNewForm(), ctx.getWcmBusiness(), ctx.getFrm()), "G979", ctx -> getContractDetails(ctx.getPeriod(), ctx.getWcmJurisdiction(), ctx.getNewForm(), ctx.getWcmBusiness(), ctx.getFrm()) );
Now your loop becomes drastically simpler:
var formDetails = new inferForms.buildFormsMap(); FormProcessingContext context = new FormProcessingContext(account, state, ...); // Populate all parameters here for (Form form : formDetails.values()) { String formNumber = form.getFormNumber(); Consumer<FormProcessingContext> handler = FORM_HANDLERS.get(formNumber); if (handler != null) { handler.accept(context); } else { // Handle unknown form numbers (log a warning, throw an error, etc.) } }
Second: Using Inheritance/Polymorphism Without Switch Statements
If you want to refactor those standalone methods into an object-oriented inheritance structure, you don't need a switch statement to instantiate subclasses. Instead, use a factory map to link form numbers to processor class suppliers.
First, define an interface for all form processors:
interface FormProcessor { void process(FormProcessingContext context); }
Then create concrete classes for each type of processing logic:
class ExclusionDetailsProcessor implements FormProcessor { @Override public void process(FormProcessingContext context) { getExclusionDetails(context.getAccount(), context.getState(), context.getForm(), context.getBusinessDealing()); } } class PartnershipDetailsProcessor implements FormProcessor { @Override public void process(FormProcessingContext context) { getPartnershipDetails(context.getAccount(), context.getState(), context.getForm(), context.getBusinessDealing()); } } // Repeat for BrokerageDetailsProcessor, LocationDetailsProcessor, ContractDetailsProcessor
Now create a factory map that gives you the right processor for each form number:
private static final Map<String, Supplier<FormProcessor>> PROCESSOR_FACTORY = Map.of( "A1345", ExclusionDetailsProcessor::new, "B254", ExclusionDetailsProcessor::new, "B297", PartnershipDetailsProcessor::new, "C397", BrokerageDetailsProcessor::new, "D972", BrokerageDetailsProcessor::new, "E192", BrokerageDetailsProcessor::new, "E299", BrokerageDetailsProcessor::new, "F254", LocationDetailsProcessor::new, "F795", LocationDetailsProcessor::new, "G642", ContractDetailsProcessor::new, "G979", ContractDetailsProcessor::new );
Your loop now looks like this:
var formDetails = new inferForms.buildFormsMap(); FormProcessingContext context = new FormProcessingContext(account, state, ...); for (Form form : formDetails.values()) { String formNumber = form.getFormNumber(); Supplier<FormProcessor> processorSupplier = PROCESSOR_FACTORY.get(formNumber); if (processorSupplier != null) { FormProcessor processor = processorSupplier.get(); processor.process(context); } else { // Handle unknown form numbers } }
Key Benefits of This Approach
- No more duplicate code: Repeated form numbers point to the same processor/supplier, so you only define the logic once.
- No switch statements: Adding a new form number just requires adding a new entry to the map (and a new processor class if needed), which follows the Open/Closed Principle (open for extension, closed for modification).
- Cleaner separation of concerns: Each processor class handles exactly one type of form logic, making your code easier to test and debug.
Answers to Your Specific Questions
Do I need a switch statement to instantiate subclasses with inheritance?
Nope! Using a factory map like the example above lets you directly look up the correct subclass instance by form number—no switch required.How do I eliminate duplicate case calls?
Both the handler map and factory map approaches solve this: duplicate form numbers simply reference the same handler function or processor supplier, so you don't repeat the method call logic.
内容的提问来源于stack exchange,提问作者revolver123

