遇见设计模式——工厂模式、代理模式、策略模式

遇见设计模式——工厂模式、代理模式、策略模式

记录做项目时所使用到的设计模式

工厂模式

需求:项目中定义了多种不同的代码沙箱

分别是:

  • 示例代码沙箱:跑通流程的测试方法。
  • 本地代码沙箱:自己实现方法。
  • 第三方代码沙箱:调用网上别人的方法API。

为什么要使用工厂模式

因为我们把 new 某个代码沙箱的代码写死了,如果后面项目要改用其他代码沙箱,可能要改很多地方的代码。

使用工厂模式,根据用户传入的字符串参数(代码沙箱类别),来生成对应的实现类
此处使用静态工厂模式,实现比较简单,符合我们的需求。

/**
 * 代码沙箱创建工厂(静态工厂模式)
 * 根据字符串参数
 *
 * @author Judy
 * @create 2023-10-11-16:51
 */
public class CodeSandboxFactory {
    /**
     * 创建代码沙箱示例
     * @param type 沙箱字符串类别
     * @return
     */
    public static CodeSandbox newInstance(String type) {
        //根据字符串动态生成实例,提高了通用性。
        switch (type) {
            case "example":
                return new ExampleCodeSandbox();
            case "remote":
                return new RemoteCodeSandbox();
            case "thirdParty":
                return new ThirdPartyCodeSandbox();
            default:
                return new ExampleCodeSandbox();
        }
    }
}

代理模式

需求:在调用代码沙箱前,输出请求参数日志;在代码沙箱调用后,输出响应结果日志,便于管理员去分析。

不可能每个代码沙箱类都写一遍log.info、每次调用代码沙箱前后都执行 log、

为什么要使用代理模式

使用代理模式,提供一个 Proxy来增强代码沙箱的能力(代理模式的作用就是增强能力)

  • 原本:需要用户自己去调用多次。

  • 使用代理后:不仅不用改变原本的代码沙箱实现类,而且对调用者来说,调用方式几乎没有改变,也不需要在每个调用沙箱的地方去写统计代码。

/**
 * 代理模式
 * @author Judy
 * @create 2023-10-11-17:28
 */
@Slf4j
public class CodeSandboxProxy implements CodeSandbox {
    
    private final CodeSandbox codeSandbox;

    // 也可以使用全参构造函数注解@AllArgsConstructor 
    public CodeSandboxProxy(CodeSandbox codeSandbox) {
        this.codeSandbox = codeSandbox;
    }

    @Override
    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {
        log.info("执行前(请求信息):"+executeCodeRequest);
        ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);
        log.info("执行后(响应信息):"+executeCodeResponse);
        return executeCodeResponse;
    }
}

策略模式

需求:判题策略可能会有很多种。

比如:我们的代码沙箱本身执行程序需要消耗时间,这个时间可能不同的编程语言是不同的,比如沙箱执行 Java 程序要额外花 10 秒。

为什么要使用策略模式

针对不同的情况,定义独立的策略,便于分别修改策略和维护。而不是把所有的判题逻辑、if ... else ... 代码全部混在一起写。

  1. 定义判题策略接口,让代码更加通用化
/**
 * 判题策略
 */
public interface JudgeStrategy {

    /**
     * 执行判题
     * @param judgeContext
     * @return
     */
    JudgeInfo doJudge(JudgeContext judgeContext);
}

  1. 定义 JudgeManager目的是尽量简化对判题功能的调用,让调用方写最少的代码、调用最简单。对于判题策略的选取,也是在 JudgeManager 里处理的。
    示例代码如下
/**
 * 判题管理(简化调用)
 */
@Service
public class JudgeManager {

    /**
     * 执行判题
     *
     * @param judgeContext
     * @return
     */
    JudgeInfo doJudge(JudgeContext judgeContext) {
        QuestionSubmit questionSubmit = judgeContext.getQuestionSubmit();
        //获取语言类型
        String language = questionSubmit.getLanguage();
        JudgeStrategy judgeStrategy = new DefaultJudgeStrategy();
        if ("java".equals(language)) {
            judgeStrategy = new JavaLanguageJudgeStrategy();
        }
        if ("js".equals(language)) {
            judgeStrategy = new JSLanguageJudgeStrategy();
        }
        if ("cpp".equals(language)) {
            judgeStrategy = new CPPLanguageJudgeStrategy();
        }
        // 继续判断提交的语言,创建对应语言的判题策略
        return judgeStrategy.doJudge(judgeContext);
    }

}

修改后在实现类中的调用:

@Resource
private JudgeManager judgeManager;
//------------------------------------
//👇工厂模式
CodeSandboxFactory codeSandboxFactory = new CodeSandboxFactory();
CodeSandbox codeSandbox = codeSandboxFactory.newInstance(type);

//👇代理模式
codeSandbox = new CodeSandboxProxy(codeSandbox);
ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);

//👇策略模式
JudgeInfo judgeInfo = judgeManager.doJudge(judgeContext);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值