Refactor Java Business Logic with Strategy, Factory, and Template Method Patterns
This article demonstrates step‑by‑step how to improve existing Java code by applying the Strategy, Factory, and Template Method design patterns, reducing duplicated if‑else branches, adhering to the Open‑Closed and Single‑Responsibility principles, and making the logic more extensible and maintainable.
Preface
In this article we show how to gradually refactor existing code using design patterns, focusing on Strategy, Factory, and Template Method, which are the most frequently used patterns in daily work.
1. Original Pseudocode Flow
Original code (Java) that decides market hit based on type, switch flags, and request number, with duplicated if‑else branches for enterprise and market_list.
<code>class Parameter{
int pageSize;
int pageNo;
int reqNum;
// other parameters.
}
// Logic to determine market hit
boolean isMarketHit(Parameter dto){
// Enterprise type
if(dto.type == 'enterprise'){
// Switch closed, no request
if(isEnterpriseSwitchClose){
return false;
}
// Single record
if(dto.reqNum==1){
return singleRemoteEOIinvoke(dto);
}else if(dto.reqNum>1){
return batchRemoteEOIinvoke(dto);
}
}
// Market list type
else if(dto.type=='market_list'){
if(isMarketListSwitchClose){
return false;
}
if(dto.reqNum==1){
return singleRemoteMarketinvoke(dto);
}else if(dto.reqNum>1){
return batchRemoteMarketinvoke(dto);
}
}
}
</code>The problems are that the if‑branches become bloated and adding a new type requires modifying the original class, violating the Open‑Closed Principle and Single‑Responsibility Principle.
If the number of
ifbranches grows, the code becomes bulky.
Adding a new type forces changes in the source code.
2. Applying Strategy Pattern
When multiple if…else branches can be encapsulated and swapped, the Strategy pattern can be used.
Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. An interface
IGroupLabelStrategyServicewith
processBiz(Parameter dto)and
getType()is introduced, and two concrete strategies – Enterprise and MarketList – implement the interface.
<code>// Interface
interface IGroupLabelStrategyService {
boolean processBiz(Parameter dto);
String getType();
}
// Enterprise strategy
class EnterpriseGroupLablelStrategyServiceImpl implements IGroupLabelStrategyService {
public boolean processBiz(Parameter dto){
if(isEnterpriseSwitchClose){
return false;
}
if(dto.reqNum==1){
return singleRemoteEOIinvoke(dto);
}else if(dto.reqNum>1){
return batchRemoteEOIinvoke(dto);
}
return false;
}
public String getType(){
return "enterprise";
}
}
// Market list strategy
class MarketListGroupLablelStrategyServiceImpl implements IGroupLabelStrategyService {
public boolean processBiz(Parameter dto){
if(isMarketListSwitchClose){
return false;
}
if(dto.reqNum==1){
return singleRemoteMarketinvoke(dto);
}else if(dto.reqNum>1){
return batchRemoteMarketinvoke(dto);
}
return false;
}
public String getType(){
return "market_list";
}
}
</code>3. Using Factory Pattern
Strategy implementations are injected into a map via
ApplicationContextAware, which acts as a simple factory to obtain the correct strategy based on
dto.getType().
<code>@Component
public class GroupLabelStrategyServiceFactory implements ApplicationContextAware {
private Map<String, IGroupLabelStrategyService> map = new ConcurrentHashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, IGroupLabelStrategyService> tempMap = applicationContext.getBeansOfType(IGroupLabelStrategyService.class);
tempMap.values().forEach(strategyService -> map.put(strategyService.getType(), strategyService));
}
public boolean processBiz(ParamDTO dto){
IGroupLabelStrategyService groupLabelStrategyService = map.get(dto.getType());
if(groupLabelStrategyService != null){
return groupLabelStrategyService.processBiz(dto);
}
return false;
}
}
</code>The original business method now delegates to the factory, reducing the method to a single call.
<code>boolean isMarketHit(Parameter dto){
return groupLabelStrategyServiceFactory.processBiz(dto);
}
</code>4. Applying Template Method Pattern
Define the skeleton of an algorithm while allowing subclasses to override specific steps.
Both strategies share the same sequence: switch check → single‑record call → batch call. This common flow is extracted into an abstract class
AbstractGroupLabelJudgeTemplatethat implements the template method.
<code>public abstract class AbstractGroupLabelJudgeTemplate implements IGroupLabelStrategyService {
// Template method
public boolean processBiz(Parameter dto){
if(isSwitchClose()){
return false;
}
if(dto.reqNum==1){
return singleRemote(dto);
}else if(dto.reqNum>1){
return batchRemote(dto);
}
return false;
}
// Steps to be provided by subclasses
protected abstract boolean isSwitchClose();
protected abstract boolean singleRemote(Parameter dto);
protected abstract boolean batchRemote(Parameter dto);
}
</code>Concrete strategy classes extend the template and provide implementations for the abstract steps.
<code>class EnterpriseGroupLablelStrategyServiceImpl extends AbstractGroupLabelJudgeTemplate {
protected boolean isSwitchClose(){
// enterprise switch logic
}
protected boolean singleRemote(Parameter dto){
return singleRemoteEOIinvoke(dto);
}
protected boolean batchRemote(Parameter dto){
return batchRemoteEOIinvoke(dto);
}
public String getType(){
return "enterprise";
}
}
class MarketListGroupLablelStrategyServiceImpl extends AbstractGroupLabelJudgeTemplate {
protected boolean isSwitchClose(){
// market list switch logic
}
protected boolean singleRemote(Parameter dto){
return singleRemoteMarketinvoke(dto);
}
protected boolean batchRemote(Parameter dto){
return batchRemoteMarketinvoke(dto);
}
public String getType(){
return "market_list";
}
}
</code>5. Final Thoughts
Strategy, Factory, and Template Method patterns are among the most used in everyday development; extracting them as shown can make the codebase more extensible and maintainable.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.