网站备案需要提交什么资料,wordpress怎么二次开发,wordpress p2 theme,青海公路建设信息服务网站判题机模块预开发(架构师)(工厂模式)
判题机模块
是为了把代码交个代码沙箱去处理 得到结果返回
代码沙箱 梳理判题模块和代码沙箱的关系
判题模块#xff1a;调用代码沙箱 把代码和输入交给代码沙箱去执行
代码沙箱#xff1a;只负责接受代码和输入 返回编译的结果 不负…判题机模块预开发(架构师)(工厂模式)
判题机模块
是为了把代码交个代码沙箱去处理 得到结果返回
代码沙箱 梳理判题模块和代码沙箱的关系
判题模块调用代码沙箱 把代码和输入交给代码沙箱去执行
代码沙箱只负责接受代码和输入 返回编译的结果 不负责判题
这两个模块完全解耦
我们采用API交互 为什么代码沙箱要接受和输出一组运行用例
前提我们的每道题目有多组测试用例
如果每个用例单独调用一个代码用例 会调用多次接口 需要多次网络运输 程序要多次编译 记录程序的执行状态 重复的代码不重复编译
这是一种常见的性能优化的方法 创建一个新的包
用来放代码沙箱模块 先写一个接口 package com.dduo.dduoj.judge.codesandbox;public interface CodeSandbox {ExecuteCodeRequest executeCode(ExecuteCodeRequest executeCodeRequest);
} 提高通用性
之后我们的项目代码只调用接口
不调用具体的实现类
就不用去修改名称了 便于拓展 写一下实体类
ExecuteCodeRequest请求
package com.dduo.dduoj.judge.codesandbox.model;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;Data
Builder
NoArgsConstructor
AllArgsConstructor
public class ExecuteCodeRequest {private ListString inputList;private String code;private String language;
} ExecuteCodeResponse响应 package com.dduo.dduoj.judge.codesandbox.model;import com.dduo.dduoj.model.dto.question.JudgeConfig;
import com.dduo.dduoj.model.dto.questionsubmit.JudgeInfo;import java.util.List;public class ExecuteCodeResponse {private ListString outputList;//执行信息private String message;//执行状态private Integer status;private JudgeInfo judgeInfo;
} 完善 定义不同的代码沙箱实现类
示例代码沙箱 远程代码沙箱 第三方代码沙箱 架构工作 lombok Builder注解 测试一下 package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;
import java.util.List;SpringBootTest
class CodeSandboxTest {Testvoid executeCode() {CodeSandbox codeSandbox new RemoteCodeSandbox();String code int main() { };String language QuestionSubmitLanguageEnum.JAVA.getValue();ListString inputList Arrays.asList(1 2, 3 4);ExecuteCodeRequest executeCodeRequest ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);}
} 工厂模式
但是现在问题是我们把new代码沙箱写死了 如果后面项目要改用其他沙箱
可能要改很多地方的代码 我们要使用工厂模式
根据用具传入的字符串参数 生成对应的代码沙箱实现类 package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.ThirdPartyCodeSandbox;//代码沙箱工厂 根据字符串参数 创建指定的代码沙箱示例
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();}}
} 如果确定代码沙箱示例不会出现线程安全问题
可复用
那么可以使用单例工厂模式 但是这种方式是不可取的 我们应该把这些东西放到配置里面
配置化 去改配置文件 而不是修改字符串 这就叫参数配置化 开发者只需要去修改配置文件 而不是去看项目代码 就能自定义使用项目的更多功能 先在application.yml里面去设置 再在程序里面去读取 示例 package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;
import java.util.List;SpringBootTest
class CodeSandboxTest {Value(${codesandbox.type:example})private String value;Testvoid executeCode() {CodeSandbox codeSandbox CodeSandboxFactory.NewInstance(value);String code int main() { };String language QuestionSubmitLanguageEnum.JAVA.getValue();ListString inputList Arrays.asList(1 2, 3 4);ExecuteCodeRequest executeCodeRequest ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);}
} 我们要增强代码沙箱的能力
在调用代码沙箱前 输出请求参数 在代码沙箱调用后 输出响应结果日志 package com.dduo.dduoj.judge.codesandbox.impl;import com.dduo.dduoj.judge.codesandbox.CodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;
import lombok.extern.slf4j.Slf4j;//示例代码沙箱 (仅供测试 跑通业务流程)
Slf4j
public class ExampleCodeSandbox implements CodeSandbox {Overridepublic ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {log.info(请求信息executeCodeRequest.toString());System.out.println(示例代码沙箱);return null;}
} 思考
我们每一个代码沙箱类都写一个 log.info ?
难道每次调用代码沙箱前后都要执行log ?
我们使用代理模式 提供一个Proxy 来增强代码沙箱的能力
静态代理模式 中介
调用者调用代理类 代理类去调用代码沙箱
代理类还可以做一些额外的功能
不仅不用改变原本的代码沙箱实现类 而且对调用者来说 基本也没有改变
也不需要在每一个调用代码沙箱的地方去统计代码 package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;Slf4j
AllArgsConstructor
public class CodeSandboxProxy implements CodeSandbox{private CodeSandbox codeSandbox;Overridepublic ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {log.info(代码沙箱的请求信息executeCodeRequest.toString());ExecuteCodeResponse executeCodeResponse codeSandbox.executeCode(executeCodeRequest);log.info(代码沙箱的响应信息executeCodeResponse.toString());return executeCodeResponse;}
}接下来我们就可以去修改调用方式 Test
void executeCodeByProxy() {CodeSandbox codeSandbox CodeSandboxFactory.NewInstance(value);codeSandbox new CodeSandboxProxy(codeSandbox);String code int main() { };String language QuestionSubmitLanguageEnum.JAVA.getValue();ListString inputList Arrays.asList(1 2, 3 4);ExecuteCodeRequest executeCodeRequest ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);
}