4~6次题目集总结blog
一、前言
关于家具电路系统和答题判题系统我认为最主要的难点在于类设计,我们先需要设计好父类再对子类和具体方法进行补充,就拿电路系统举例,无论是受控设备还是控制设备,具体代码都较为简单,只需简单的数学运算就能求出具体功率,但要如何将设备加入电路当中以及能够进行计算才是较为重要的,所以我们要熟悉list类的使用,能够正确的使用多态和继承,并且我们要有能根据具体情况去设计类的能力(也就是所谓的先研究需求再设计),再说到题目上,第4次题目集(答题判题系统)我认为较难,需要处理的类较多,而第5,6次题目集(家具电路系统)由于迭代不多且类设计较为清晰,难度则适中,但需要在意具体实现的代码。
二、设计与分享
第4次题目集
点击查看代码
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
class QuestionMgr {
private ArrayList<Question> questions = new ArrayList<>();
public boolean isExist(int id){
for(int i=0;i<questions.size();i++){
if(questions.get(i).getId() == id)
return true;
}
return false;
}
public void addQuestion(int id, String content,String answer){
questions.add(new Question(id,content,answer));
}
public void setInvalid(int id){
for(int i=0;i<questions.size();i++){
if(questions.get(i).getId() == id)
questions.get(i).setValid(false);
}
}
public String getCorrectAnswer(int id){
for(int i=0;i<questions.size();i++){
if(questions.get(i).getId() == id)
return questions.get(i).getAnswer();
}
return null;
}
public boolean isValid(int id){
for(int i=0;i<questions.size();i++){
if(questions.get(i).getId() == id)
return questions.get(i).isLive();
}
return false;
}
public String getContentById(int id){
for(int i=0;i<questions.size();i++){
if(questions.get(i).getId() == id)
return questions.get(i).getContent();
}
return null;
}
}
class Question {
private String content;
private int id;
private boolean live;
private String answer;
public Question(int id ,String content, String answer) {
this.content = content;
this.id = id;
this.live = true;
this.answer = answer;
}
public int getId(){
return id;
}
public boolean isLive(){
return live;
}
public String getAnswer() {
return answer;
}
public void setValid(boolean f){
this.live = f;
}
public String getContent() {
return content;
}
}
class TestPaper {
private int paperNumber;
private int questionnumber;
private ArrayList<Integer> paperQuestions = new ArrayList<>();
private ArrayList<Integer> paperScore = new ArrayList<>();
public TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
questionnumber = 0;
}
public int getQuestionNumber(){
return questionnumber;
}
public void addPaperQuestion(int number,int score){
paperQuestions.add(number);
paperScore.add(score);
questionnumber++;
}
public int getPaperNumber() {
return paperNumber;
}
public int getQuestionIdByIndex(int index){
return paperQuestions.get(index);
}
public int getScoreByIndex(int index){
return paperScore.get(index);
}
public boolean isFulll(){
int sum = 0;
for(int i=0;i<paperScore.size();i++)
sum += paperScore.get(i);
if(sum == 100)
return true;
else
return false;
}
public ArrayList<Integer> getQuestions() {
return paperQuestions;
}
public ArrayList<Integer> getQuestionScores() {
return paperScore;
}
}
class TestPaperMgr{
private ArrayList<TestPaper> paperMgr = new ArrayList<>();
public TestPaper getPaper(int id){
for(int i=0;i<paperMgr.size();i++){
if(paperMgr.get(i).getPaperNumber() == id)
return paperMgr.get(i);
}
return null;
}
public void updatePaper(TestPaper paper){
for(int i=0;i<paperMgr.size();i++){
if(paperMgr.get(i).getPaperNumber() == paper.getPaperNumber()){
paperMgr.remove(i);
break;
}
}
paperMgr.add(paper);
}
}
class StudentMgr{
ArrayList<Student> allStudents = new ArrayList<>();
public String getStudentNameById(String id){
for(int i=0;i<allStudents.size();i++){
if(allStudents.get(i).getId().equals(id))
return allStudents.get(i).getName();
}
return null;
}
public void addStudents(ArrayList<Student> stus){
for(int i=0;i<stus.size();i++)
allStudents.add(stus.get(i));
}
}
class Student {
private String name;
private String id;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class AnswerSheet {
private TestPaper testPaper;
private QuestionMgr questionMgr;
private ArrayList<Integer> questionsOder = new ArrayList<>();
private ArrayList<String> answers = new ArrayList<>();
public AnswerSheet(TestPaper testPaper,QuestionMgr mgr) {
this.testPaper = testPaper;
this.questionMgr = mgr;
}
public void addAnswer(int index,String ans){
questionsOder.add(index);
answers.add(ans);
}
public void outputResults(String studentId, String studentName) {
if (!testPaper.isFulll()) {
System.out.println("alert: full score of test paper" + testPaper.getPaperNumber() + " is not 100 points");
}
int cnt = 0;
int sumScore = 0;
String strScore = "";
if(studentName == null)
strScore = studentId + " not found";
else
strScore = studentId+" "+ studentName+":";
ArrayList<String> logs = new ArrayList<>();
int ok = 0,err=0;
for(int i=0;i<questionsOder.size();i++){
int index = questionsOder.get(i);
String ans = answers.get(i);
if(index > testPaper.getQuestionNumber())
continue;
cnt++;
int questionId = testPaper.getQuestionIdByIndex(index-1);
int questionScore = testPaper.getScoreByIndex(index-1);
if(!questionMgr.isExist(questionId)){
System.out.println("non-existent question~0");
}else{
if(!questionMgr.isValid(questionId)){
String ls = "the question "+ String.valueOf(index) +" invalid~0";
logs.add(ls);
}else{
String right = questionMgr.getCorrectAnswer(questionId);
if(right.equals(ans)){
System.out.println(questionMgr.getContentById(questionId)+"~"+ans+"~true");
strScore = strScore +" " + String.valueOf(questionScore);
sumScore += questionScore;
ok++;
}else{
System.out.println(questionMgr.getContentById(questionId)+"~"+ans+"~false");
strScore = strScore +" 0";
err++;
}
}
}
}
for(int i=0;i<logs.size();i++){
strScore = strScore +" 0";
err++;
System.out.println(logs.get(i));
}
for(int i = (ok+err);i<testPaper.getQuestionNumber();i++)
strScore = strScore +" 0";
if(cnt < testPaper.getQuestionNumber())
System.out.println("answer is null");
if(studentName == null)
System.out.println(strScore);
else{
strScore = strScore + "~"+String.valueOf(sumScore);
System.out.println(strScore);
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
TestPaperMgr paperMgr = new TestPaperMgr();
QuestionMgr questionMgr = new QuestionMgr();
StudentMgr stuMgr = new StudentMgr();
String studentId="";
String studentName = "";
TestPaper currentpaper = null;
AnswerSheet answerSheet = null;
while (true) {
String line = scanner.nextLine();
if (line.equals("end")) {
break;
}
Matcher matcher;
if ((matcher = Pattern.compile("#N:(\\d+) #Q:(.*?) #A:(\\d+)").matcher(line)).matches()) {
int number = Integer.parseInt(matcher.group(1));
String questionContent = matcher.group(2);
String answer = matcher.group(3);
questionMgr.addQuestion(number, questionContent, answer);
} else if ((matcher = Pattern.compile("#T:(\\d+) (.+)").matcher(line)).matches()) {
int paperNumber = Integer.parseInt(matcher.group(1));
TestPaper paper = paperMgr.getPaper(paperNumber);
if(paper == null){
paper = new TestPaper(paperNumber);
}
String[] parts = matcher.group(2).split(" ");
for(int i=0;i<parts.length;i++){
String[] pt = parts[i].split("-");
int questionNumber = Integer.parseInt(pt[0]);
int score = Integer.parseInt(pt[1]);
paper.addPaperQuestion(questionNumber, score);
}
paperMgr.updatePaper(paper);
} else if ((matcher = Pattern.compile("#X:(\\d+) (.+)").matcher(line)).matches()) {
int index = line.indexOf(":");
line = line.substring(index+1);
String[] parts = line.split("-");
ArrayList<Student> stus = new ArrayList<>();
for(int i=0;i<parts.length;i++){
String[] stu = parts[i].split(" ");
if(stu.length==2){
stus.add(new Student(stu[0],stu[1]));
}
}
stuMgr.addStudents(stus);
} else if ((matcher = Pattern.compile("#S:(\\d+) (\\d+) (.+)").matcher(line)).matches()) {
int paperNmb = Integer.parseInt(matcher.group(1)); //获取试卷编号
currentpaper = paperMgr.getPaper(paperNmb); //根据试卷编号找到试卷
if(currentpaper != null){
studentId = matcher.group(2);
studentName = stuMgr.getStudentNameById(studentId);
String[] ques = matcher.group(3).split(" ");
answerSheet = new AnswerSheet(currentpaper,questionMgr);
for(int i=0;i<ques.length;i++){
String ans = ques[i].substring(ques[i].indexOf(":")+1);
String[] pts = ans.split("-");
if (pts.length == 2){
int questionNumber = Integer.parseInt(pts[0]);
String answer = pts[1];
answerSheet.addAnswer(questionNumber,answer);
}
}
}
}else if(line.startsWith("#D:N-")){
int index = line.indexOf("-");
if(index < line.length()){
int id = Integer.parseInt(line.substring(index+1));
questionMgr.setInvalid(id);
}
} else {
System.out.println("wrong format:"+line);
}
}
if(currentpaper == null){
System.out.println("The test paper number does not exist");
}else {
answerSheet.outputResults(studentId, studentName);
}
}
}

主要的类有Testpaper(试卷类)Answersheet(答卷类)Question(问题类)Student(学生类),其余的mgr都是负责正则表达式收集信息然后再管理,逐个分析学生类是最为简单的,只需要学生个人信息及答题分数(至于判题的具体实现甚至都不是在学生类中实现),再是问题类,它关乎答卷类及试卷类,试卷类中需要存储问题的信息,而答卷类则要有问题的标准答案,(这样看其实前两个类本身的设计也并不复杂,重点在于类间的关系)但本身类中则是最基础的get及set甚至不需要立马完成,Test及Answer我们放在一起看分析,可以看到两个类都需要用到两个Arraylist去储存信息,Test通过题号去添加问题,而Answer也是通过题号来进行比较答案并且负责记录将答题的信息给到学生。
第5,6次题目集
点击查看代码
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.DecimalFormat;
class Circuit {
protected static LinkedHashMap<String,Device> deviceMap = new LinkedHashMap<>();
public Circuit() {
}
public void update() {
Device previous =null;
for(Device device : deviceMap.values()) {
if(previous!=null) {
device.setV1(previous.getV2());
}
if(device instanceof Switch) {
((Switch) device).update();
}else if(device instanceof Gearspeed) {
((Gearspeed) device).update();
}else if(device instanceof Unitgear) {
((Unitgear) device).update();
}else if(device instanceof Light1) {
((Light1) device).update();
}else if(device instanceof Light2) {
((Light2) device).update();
}else if(device instanceof Fan) {
((Fan) device).update();
}
previous=device;
}
}
public void getDeviceStates() {
for (Map.Entry<String, Device> entry : deviceMap.entrySet()) {
System.out.print("@" + entry.getKey() + ":");
entry.getValue().display();
}
}
}
class Device {
protected double v1;
protected double v2;
public Device() {}
public Device(double v1,double v2) {
this.v1=0;
this.v2=0;
}
public double getV1() {
return v1;
}
public void setV1(double v1) {
this.v1 = v1;
}
public double getV2() {
return v2;
}
public void setV2(double v2) {
this.v2 = v2;
}
public void display() {
}
}
class device1 extends Device {
public device1(double v1,double v2) {
this.v1=v1;
this.v2=v2;
}
public device1() {
}
}
class device2 extends Device{
protected double v;
public device2() {
}
public device2(double v1,double v2,double v) {
this.v1=v1;
this.v2=v2;
this.v=v;
}
}
class Fan extends device2{
private double lux=0;
public Fan(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Fan() {
}
public double getLux() {
return lux;
}
public void setlux(double lux) {
this.lux=lux;
}
public void update() {
if(this.v1<80) {
this.lux=0;
}
if(this.v1>=80&&this.v1<=150) {
this.lux=4*this.v1-240;
}
if(this.v1>=150) {
this.lux=360;
}
}
public void display() {
System.out.println(Math.round(this.lux));
}
}
class Gearspeed extends device1{
private double v1 = 220;
private int gear=0;
public Gearspeed() {
}
public Gearspeed(int gear,double v1,double v2) {
super(v1,v2);
this.gear=gear;
this.gear=0;
}
public int getGear() {
return gear;
}
public void up() {
if(this.gear<3)
this.gear++;
}
public void down() {
if(this.gear>0)
this.gear--;
}
public void update() {
if (this.v1 == 0) {
this.v2 = 0;
} else {
switch (this.gear) {
case 0:
this.v2 = 0;
break;
case 1:
this.v2 = 0.3 *this.v1;
break;
case 2:
this.v2 = 0.6 *this.v1;
break;
case 3:
this.v2 = 0.9 * this.v1;
break;
default:
this.v2 = 0;
break;
}
}
}
public void display() {
System.out.println(this.gear);
}
}
class Light1 extends device2{
private double v2 = 0;
private double lux=0;
public Light1(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Light1() {
}
public double getLux() {
return lux;
}
public void update() {
if(this.v1>=0&&this.v1<=9) {
this.lux=0;
}else if(this.v1>9&&this.v1<=220) {
this.lux=(5.0/7.0)*v1+(300.0/7.0);
}else if(this.v1>220) {
this.lux=200;
}
}
public void display() {
System.out.println((int)(this.lux));
}
}
class Light2 extends device2{
private double v2 = 0;
private double lux=0;
public Light2(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Light2() {
}
public double getLux() {
return lux;
}
public void update() {
if(this.v1>0) {
this.lux=180;
}
else if(this.v1==0) {
this.lux=0;
}
}
public void display() {
System.out.println((int)this.lux);
}
}
class Switch extends device1{
private int state;
public Switch() {
}
public Switch(double v1,double v2,int state) {
super(v1,v2);
this.state=0;
}
public int getState() {
return this.state;
}
public void setState() {
if (this.state==1) {
this.state=0;
}else if(this.state==0) {
this.state=1;
}
}
public void update() {
if(this.state==1) {
this.v2=this.v1;
}else if(this.state==0) {
this.v2=0;
}
}
public void display() {
if(this.state==0) {
System.out.println("tuened on");
}else if(this.state==1) {
System.out.println("closed");
}
}
}
class Unitgear extends device1{
private double v1 = 220;
private double gear=0;
public Unitgear() {
}
public Unitgear(double gear,double v1,double v2) {
super(v1,v2);
if(gear>=0&&gear<=1)
this.gear=gear;
this.gear=0;
}
public double getGear() {
return gear;
}
public void setGear(double gear) {
if(gear>=0&&gear<=1)
this.gear = gear;
}
public void update() {
this.v2=((double)this.v1*this.gear);
}
public void display() {
DecimalFormat decimalFormat = new DecimalFormat("#0.00");
String format = decimalFormat.format(this.gear);
System.out.println(format);
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Circuit circuit = new Circuit();
Device device = new Device();
while(true) {
String input = scanner.next();
if(input.startsWith("[")) {
String regex = "[A-Z]\\d+-2";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while(matcher.find()) {
String inputs = input.substring(1,3);
if(inputs.startsWith("K")) {
Device switchs = new Switch();
Circuit.deviceMap.put(inputs, switchs);
}else if(inputs.startsWith("F")) {
Device gears = new Gearspeed();
circuit.deviceMap.put(inputs, gears);
}else if(inputs.startsWith("L")) {
Device unit = new Unitgear();
circuit.deviceMap.put(inputs, unit);
}else if(inputs.startsWith("B")) {
Device light1 = new Light1();
circuit.deviceMap.put(inputs, light1);
}else if(inputs.startsWith("R")) {
Device light2 = new Light2();
circuit.deviceMap.put(inputs, light2);
}else if(inputs.startsWith("D")) {
Device fan = new Fan();
Circuit.deviceMap.put(inputs, fan);
}
if(Circuit.deviceMap.size()==1){Circuit.deviceMap.get(inputs).setV1(220);}
}
}else if(input.startsWith("#K")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("K")) {
((Switch) entry.getValue()).setState();
break;
}
}
}else if(input.startsWith("#F")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("F")) {
if(input.substring(3,4).equals("+")) {
((Gearspeed) entry.getValue()).up();
}else if(input.substring(3,4).equals("-")) {
((Gearspeed) entry.getValue()).down();
}
break;
}
}
}else if(input.startsWith("#L")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("L")) {
double input1 = Double.parseDouble(input.substring(4));
((Unitgear) entry.getValue()).setGear(input1);
break;
}
}
}else if(input.equals("end")) {
break;
}
}
circuit.update();
circuit.getDeviceStates();
}
}

对于家具电路系统,我认为只需要细说Device(设备)及Circuit(电路)类即可,对于具体的受控设备和控制设备其代码都是数学公式或者调整状态的于总结而言并不重要,基本都是update()去更新信息dispaly()去展示信息,对于Device我设置了两个子类1和2,分别对应控制及受控设备,这样做的好处是在电路连接时你可以清楚的录入设备并分别进行判断,并且在电路中可以更快速的判断前后的电压,而电路类我其实一直没想明白所以只写了串联电路,在第五次题目集中我通过for循环遍历list数组再判断为什么类添加进电路当中,但这是因为只有串联电路,以至于并联电路没有解决,但我的想法是当读到需要并联的设备时则再new一个电路以此来达到并联的目的,可这只是个想法再加上此次有电阻我没有想好要怎么将电压在整个电路中进行分压计算,导致没有做出第六次题目集。我个人觉得电路会比答题系统简单,因为答题系统要负责的父类较多这就导致关系较为复杂,虽然电路有很多子类但之间的耦合性不高而且极其方便更改,重点只要考虑设备与电路关系即可。
三、采坑心得
首先我想说的就是关于父类及子类的问题,在电路中我在父类Device中定义了每个电压都为0,然后在子类设备super(),以此希望覆盖掉再重新接入一个电压,但是这是不行的并且导致了我在写完代码运行时发现,无论如何受控设备的功率都为0,我根本没注意到之前的设计有问题,不管怎么调试都显示控制设备传递电压到下一步的受控设备都为0,我一直以为是我电路连接时有问题毕竟这样看起来像是传递电压出了错误,我还是在复写设备类时偶然更改才发现的,子类的复写无法覆盖掉父类;
还有就是在需求分析时可以尝试去用纸笔规范的记录下然后完整的浏览思考一遍最起码对我个人而言会让我对于类的设计更加清晰一些;
再说一个关于list使用的问题,LinkedHashMap是一个有序的,并且你可以根据accessOrder来控制节点以访问元素,并且值得一提的是它可以根据访问顺序或插入顺序来访问元素,这种双向链表查找效率快且维护插入顺序,我个人认为在需要按顺序去解决问题的情景下较为好用,当然如果是答题判题程序,是按我这种序号来对比的情况就不需要用到,但也可以根据顺序来逐一比较(仅凭个人喜好选择);
关于接口,其实这是一个非常好用的点,可以帮助减少代码冗余,我要说的是要注意接口作为一个抽象类,它是要被类实现的而非被类继承,当我们写非抽象类如果实现了结果一定要实现接口中的所以方法的具体实现。
四、改进建议
1.减少类型检查与利用多态性:
当前在Circuit类的update方法中使用了大量的instanceof类型检查来判断设备的具体类型。这不仅违反了开闭原则,也使得代码难以维护。一个更好的做法是定义一个通用的update方法在Device接口中,并让各个子类自行实现其特有的更新逻辑。这样一来,Circuit类在调用update方法时无需关心设备的具体类型,只需调用接口定义的方法即可。
2.引入管理器:
使用管理类以方便操作例如目前Circuit类直接管理了所有的设备,但随着设备数量的增加,这种管理方式可能会变得难以维护。因此,准备引入一个专门的CircuitManager类来负责设备的添加、删除和更新操作。CircuitManager类可以维护一个设备列表,并提供相应的方法来操作这些设备。这样,Circuit类可以专注于其本身的逻辑,而设备的管理则由CircuitManager类负责。以此逻辑去完善电路。
封装设备处理逻辑:
为了提高代码的可读性和可维护性,可以将不同设备的处理逻辑封装到单独的方法中。例如,可以将开关设备的状态切换逻辑封装到switchState方法中,将调速设备的档位调整逻辑封装到adjustSpeed方法中。这样一来,每个设备类都只需要关注其特有的逻辑,而无需处理其他设备的逻辑。同时,这也使得代码更加模块化,方便进行迭代和修改。
使用接口定义设备状态和操作:
为了进一步提高代码的灵活性和可扩展性,可以为设备定义一个统一的接口,用于描述设备的状态和操作。例如,可以定义一个DeviceState接口来描述设备的状态(如开启、关闭、调速等),并定义一个DeviceOperation接口来描述对设备的操作(如切换状态、调整档位等)。这样,不同的设备类只需要实现这些接口即可与电路系统进行交互,无需关心具体的实现细节。
将设备即控制设备都设置接口以更新设备状态和调整设备参数。
可以使用多态代替类型检查程序中包含多个if-else语句来检查设备类型并执行相应的操作。这可以通过Java的多态性来简化,使得代码更加简洁和易于扩展。
五、总结
首先,通过这次的学习和实践,我深刻体会到了面向对象编程(OOP)的魅力和实用性。通过接口和多态性的应用,我能够理解并应用设计模式,使程序更加灵活和可扩展。例如,Circuit类能够容纳任何实现了Device接口的对象,这种设计使得程序具有很高的灵活性和可重用性。
其次,我在实践中进一步理解了组合与继承的关系。通过继承,我可以快速地创建具有相似特性的新设备类;而通过组合,我可以将不同的设备组合成复杂的电路结构,实现更高级的功能。这种组合与继承的设计思想不仅有助于代码的复用和组织,而且方便我进行迭代和修改。
此外,我也认识到了代码可读性和可维护性的重要性。通过封装不同的处理逻辑到单独的方法中,我可以使代码更加清晰和易于理解。同时,使用合适的命名和注释也能够提高代码的可读性,使其他开发者能够更快地理解和修改代码。
在未来,我将继续深入学习Java的异常处理机制,以确保程序的健壮性和稳定性。异常处理是确保程序能够优雅地处理错误情况的关键部分,它能够帮助我更好地识别和解决潜在的问题。
同时,我也计划学习更多的设计模式,如工厂模式、单例模式、观察者模式等。这些设计模式是软件开发中的宝贵财富,它们能够帮助我优化代码结构,提高程序的可维护性和可扩展性。通过学习和应用这些设计模式,我相信我能够编写出更加健壮和高效的代码。

浙公网安备 33010602011771号