设计模式 | 基于工厂&策略模式的返奖流程实现

本文通过一个返奖流程的业务场景,结合策略模式和工厂模式,展示了如何设计和实现灵活的业务逻辑。首先介绍了返奖流程,然后分析业务流程并应用开闭原则,将返奖规则抽象为策略,使用策略模式处理不同用户类型的返奖策略。接着,通过工厂模式创建和使用这些策略。最终,展示了代码实现,包括抽象策略、具体策略、上下文和工厂,以及客户端如何使用这些模式。这种组合使用提高了代码的扩展性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


theme: vue-pro

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

我们通过两篇文章《挑战工厂模式》《挑战策略模式》分别介绍了两种模式的模型、适用场景、优缺点。在我们实际开发业务中,往往单独使用一种模式是不能解决实际问题,有时我们需要根据实际需求组合模式达到目的,这篇文章我们来讲讲基于两种模式混合实现一个返奖逻辑。

一、返奖流程介绍

返奖流程的业务逻辑视图如下:

image.png - 首先我们要根据访问的用户Id确定用户的特征信息,比如新用户、老用户等等。 - 接着要判断用户的特征,选择具体的返奖策略,并执行策略。 - 返奖策略执行完成后,对所有的用户都有统一的处理逻辑,比如持久化,通知其它服务等等。

二、业务流程分析

通过流程分析,可以很清楚的看到,对于所有特征的用户,经历的返奖流程是保持一致的,唯一有区别或者说是有变化的是返奖规则。对于这样的业务流程,我们可参考开闭原则

Software entities (classes, modules, functions) should be open for extension but closed for modification。

官方定义开闭原则:软件实体(包括类、模块、功能等)应该对扩展开放,但是对修改关闭。对扩展开放,表示模块通过扩展的方式去应对需求的变化;对修改关闭,表示当需求变化时,应该尽可能关闭对模块源代码的修改。

所以套用开闭原则,我们应该对于返奖流程保持封闭,对于极有可能扩展的返奖规则保持开放。我们将返奖规则抽象为返奖策略,即针对不同用户类型的不同返奖方案,我们视为不同的返奖策略,不同的返奖策略会产生不同的返奖金额结果。

很显然,我们现在抽象了一个返奖策略,当然是要使用策略模式,然后返奖策略的产生需要统一产生,所以我们需要一个工厂,即使用工厂模式

三、代码实现

首先我们要定义一个抽象的策略,它能完成两件事情,第一步是执行返奖策略并获取金额,第二步是执行获得返奖策略后的操作。

​ public interface RewardStrategy {   int rewardBy(String userTrait);   void afterReward(String userTrait,int rewardAmount); }

因为第二个步骤的执行对于所有用户执行逻辑都是一致的,所以准备一个抽象类去实现afterReward方法。

public abstract class AbstractRewardStrategy implements RewardStrategy{   @Override   public abstract int rewardBy(String userTrait); ​   @Override   public void afterReward(String userTrait, int rewardAmount) {       //执行奖励策略后统一要处理的事情       System.out.println("do something after reward");   } }

接着就是具体的返奖策略类,我们默认实现NewUserRewardStrategyOldUserRewardStrategy两个返奖策略。

public class NewUserRewardStrategy extends AbstractRewardStrategy{   @Override   public int rewardBy(String userTrait) {       return 10;   } } ​ public class OldUserRewardStrategy extends AbstractRewardStrategy{   @Override   public int rewardBy(String userTrait) {       //老用户还想有奖励?       return 0;   } }

具体的策略准备好了,但是对于策略模式我们还要准备一个使用的context

public class RewardContext {   final RewardStrategy rewardStrategy;       public RewardContext(RewardStrategy rewardStrategy){       this.rewardStrategy = rewardStrategy;   } ​   public void doStrategy(String userTrait){       final int rewardAmount = rewardStrategy.rewardBy(userTrait);       rewardStrategy.afterReward(userTrait,rewardAmount);   } }

至此,策略模式的部分完成,接着我们来实现工厂模式的部分。

public abstract class StrategyFactory<T> {   abstract RewardStrategy createStrategy(Class<T> c); } ​ public class FactorRewardStrategyFactory extends StrategyFactory {   @SneakyThrows   @Override   RewardStrategy createStrategy(Class clazz) {       return (RewardStrategy)clazz.newInstance();   } }

然后我们客户端的使用的代码如下。

public class RewardApp { ​   static final String NEW_USER_TRAIT = "traitOfNewUser";   static final String OLD_USER_TRAIT = "traitOfOldUser"; ​   public static void main(String[] args) {       if(args == null || args.length ==0){           throw new IllegalArgumentException("args error");       }       final String userTrait = args[0];       final FactorRewardStrategyFactory factorRewardStrategyFactory = new FactorRewardStrategyFactory();       RewardStrategy strategy;       if(userTrait.equals(NEW_USER_TRAIT)){           strategy = factorRewardStrategyFactory.createStrategy(NewUserRewardStrategy.class);       }else if(userTrait.equals(OLD_USER_TRAIT)){           strategy = factorRewardStrategyFactory.createStrategy(OldUserRewardStrategy.class);       }else{           throw new IllegalArgumentException("Unknown userTrait");       }       final RewardContext rewardContext = new RewardContext(strategy);       rewardContext.doStrategy(userTrait);   } }

至此,返奖流程实现完成,URL类图如下。

StrategyFactory.png

四、总结

策略模式保证了我们可以根据业务需求动态的切换策略,而不必改动我们的代码逻辑。工厂模式帮助我们去使用具体的策略,而不再关心创建对象过程中的逻辑。

通过两种模式的组合,当我们需要丰富策略时,我们只是需要继承实现AbstractRewardStrategy抽象类,不必动其它的代码逻辑。这样提高了服务的扩展性,在一定程度上做到了高内聚、低耦合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值