7-2 sda-2.2 设计模式-Composite-Visitor
已知年级由班级组成、班级由学生组成,在成绩发布之后每个学生会根据自身成绩的情况做出不同的响应,请基于组合(Composite)模式与访问者(Visitor)模式设计该程序。
主程序关键代码:
public class Main {
public static void main(String[] args) {
/*
* 输入代码,请保留
* 数组inputs对应控制台输入
* inputs[0]: 0 - 年级、班级、学生等数据在程序内由createObjectStructure方法创建;
* 1 - 年级、班级、学生等数据从控制台输入并经过parseInputs方法分析得到;
* inputs[1]: {g01:{c01:{s01-Jack-80,s02-Tom-70},c02:{s03-Green-90,s04-Smith-70}},g02:{c03:{s05-Jones-75,s06-Jerry-85}}}
* */
Scanner sc = new Scanner(System.in);
String[] inputs = new String[2];
for(int i=0;i<inputs.length;i++){
inputs[i]=sc.nextLine();
}
sc.close();
visitor = new ...(); //创建访问者
...[] grades=null;
// 根据输入情况来选择采用何种方式创建年级、班级、学生等对象,并将其组合。
if (Integer.parseInt(inputs[0])==0)
grades = createObjectStructure();
else
grades = parseInputs(inputs[1]);
....accept(visitor); //接受访问者对象,输出结果
...
}
/* 创建年级、班级、学生对象并将其组合起来 */
public static Grade[] createObjectStructure() {
/* 创建的年级、班级、学生对象如下:
年级:g01,该年级有以下班级:
班级:c101,该班级有以下学生
学生:s01,Jack,70
----s04,Green,50
--c102
----s02,Tom,80
----s05,Smith,60
g02
--c103
----s03,Jerry,90
----s06,Jones,70
*/
...
}
/* 通过分析strInput字符串创建年级、班级、学生对象并将其组合起来 */
public static Grade[] parseInputs(String strInput) {
...
}
}
输入格式:
第1行:创建对象的方式,0或1,含义参见主程序关键代码注释
第2行:年级、班级、学生数据,格式为
{年级1:{班级1:{学号1-姓名1-成绩1,...},...},...}
参见输入输出样例
输出格式:
年级
--班级(人数)
----学号1,姓名1,成绩1,passed
----学号2,姓名2,成绩2,failed
passed表示通过考试,即分数大于或等于60分
failed表示未通过考试,即分数小于60分
输入样例:
当第一行输入为0时,第二行可以输入任意内容,对结果无影响
0
123
当第一行输入为1时,第二行应按指定格式输入年级、班级、学生等实体内容
1
{g01:{c01:{s01-Jack-80,s02-Tom-70},c02:{s03-Green-90,s04-Smith-70}},g02:{c03:{s05-Jones-75,s06-Jerry-85}}}
输出样例:
当第一行输入为0时,输出内容确定,必定为以下内容:
g01
--c101(2)
----s01,Jack,70,passed
----s04,Green,50,failed
--c102(2)
----s02,Tom,80,passed
----s05,Smith,60,passed
g02
--c103(2)
----s03,Jerry,90,passed
----s06,Jones,70,passed
当第一行输入为1时,输出内容由第二行输入数据决定
g01
--c01(2)
----s01,Jack,80,passed
----s02,Tom,70,passed
--c02(2)
----s03,Green,90,passed
----s04,Smith,70,passed
g02
--c03(2)
----s05,Jones,75,passed
----s06,Jerry,85,passed
用栈优雅完成,测试点全过
import java.util.*;
interface Element {
void accept(Visitor visitor);
String getType();
String getId();
void setId(String id);
String getIn();
}
interface Visitor {
void visit(Grade grade);
void visit(Clazz clazz);
void visit(Student student);
}
class Clazz implements Element{
private String id;
private String in;
private final List<Student> studentList = new ArrayList<>();
public Clazz(String id) {
this.in = id;
this.id = id.replaceAll("\\{","").replaceAll("\\}","");
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
Collections.reverse(studentList);
studentList.forEach(student -> {
student.accept(visitor);
});
}
@Override
public String getType() {
return "c";
}
public Clazz add(Element element) {
studentList.add((Student) element);
return this;
}
public Clazz remove(Element element) {
studentList.remove((Student) element);
return this;
}
public List<Student> getStudentList() {
return studentList;
}
@Override
public String getIn() {
return in;
}
}
class Grade implements Element{
private String id;
private String in;
private final List<Clazz> clazzList = new ArrayList<>();
public Grade(String id) {
this.in = id;
this.id = id.replaceAll("\\{","").replaceAll("\\}","");
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
Collections.reverse(clazzList);
clazzList.forEach(clazz -> {
clazz.accept(visitor);
});
}
@Override
public String getType() {
return "g";
}
public Grade add(Element element) {
clazzList.add((Clazz) element);
return this;
}
public Grade remove(Element element) {
clazzList.remove((Clazz) element);
return this;
}
public List<Clazz> getClazzList() {
return clazzList;
}
@Override
public String getIn() {
return in;
}
}
class Student implements Element{
private String id;
private String name;
private int score;
private String in;
public Student(String in) {
this.in = in;
in = in.replaceAll("\\{","").replaceAll("\\}","");
this.id = in.split("-")[0];
this.name = in.split("-")[1];
this.score = Integer.parseInt(in.split("-")[2].replaceAll("}*",""));
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public String getType() {
return "s";
}
@Override
public String getIn() {
return in;
}
}
class VisitorA implements Visitor{
@Override
public void visit(Grade grade) {
System.out.println(grade.getId());
}
@Override
public void visit(Clazz clazz) {
System.out.println("--"+clazz.getId()+"("+ clazz.getStudentList().size()+")");
}
@Override
public void visit(Student student) {
String state;
if (student.getScore()>=60) {
state = "passed";
}
else {
state = "failed";
}
System.out.println("----"+student.getId()+","+student.getName()+","+student.getScore()+","+state);
}
}
class Main {
public static void main(String[] args) {
/*
* 输入代码,请保留
* 数组inputs对应控制台输入
* inputs[0]: 0 - 年级、班级、学生等数据在程序内由createObjectStructure方法创建;
* 1 - 年级、班级、学生等数据从控制台输入并经过parseInputs方法分析得到;
* inputs[1]: {g01:{c01:{s01-Jack-80,s02-Tom-70},c02:{s03-Green-90,s04-Smith-70}},g02:{c03:{s05-Jones-75,s06-Jerry-85}}}
* */
Scanner sc = new Scanner(System.in);
String[] inputs = new String[2];
for(int i=0;i<inputs.length;i++){
try {
inputs[i]=sc.nextLine();
}
catch (Exception ignored) {
}
}
sc.close();
Visitor visitor = new VisitorA(); //创建访问者
Grade[] grades=null;
// 根据输入情况来选择采用何种方式创建年级、班级、学生等对象,并将其组合。
if (Integer.parseInt(inputs[0])==0)
grades = createObjectStructure();
else
grades = parseInputs(inputs[1]);
for (Grade grade:grades) {
grade.accept(visitor); //接受访问者对象,输出结果
}
}
/* 创建年级、班级、学生对象并将其组合起来 */
public static Grade[] createObjectStructure() {
/* 创建的年级、班级、学生对象如下:
年级:g01,该年级有以下班级:
班级:c101,该班级有以下学生
学生:s01,Jack,70
----s04,Green,50
--c102
----s02,Tom,80
----s05,Smith,60
g02
--c103
----s03,Jerry,90
----s06,Jones,70
*/
List<Grade> gradeList = new ArrayList<>();
Grade grade1 = new Grade("g01");
Grade grade2 = new Grade("g02");
grade1.add(new Clazz("c101").add(new Student("s01-Jack-70")).add(new Student("s04-Green-50"))).add(new Clazz("c102").add(new Student("s02-Tom-80")).add(new Student("s05-Smith-60")));
grade2.add(new Clazz("c103").add(new Student("s03-Jerry-90")).add(new Student("s06-Jones-70")));
Collections.reverse(grade1.getClazzList());
Collections.reverse(grade2.getClazzList());
grade1.getClazzList().forEach(clazz -> {
Collections.reverse(clazz.getStudentList());
});
grade2.getClazzList().forEach(clazz -> {
Collections.reverse(clazz.getStudentList());
});
gradeList.add(grade1);
gradeList.add(grade2);
return gradeList.toArray(new Grade[0]);
}
/* 通过分析strInput字符串创建年级、班级、学生对象并将其组合起来 */
public static Grade[] parseInputs(String strInput) {
strInput = strInput.replaceAll(" ","");
if (strInput.isEmpty()) {
return new Grade[0];
}
List<Grade> gradeList = new ArrayList<>();
Stack<Element> stack = new Stack<>();
for (String comma:strInput.split(",")) {
for (String colon:comma.split(":")) {
switch(colon.replaceAll("\\{","").replaceAll("\\}","").charAt(0)) {
case 'g':
stack.push(new Grade(colon));
break;
case 'c':
stack.push(new Clazz(colon));
break;
case 's':
stack.push(new Student(colon));
break;
}
while (colon.charAt(colon.length()-1) == '}') {
List<Element> temp = new ArrayList<>();
while (!stack.isEmpty()) {
if (stack.lastElement().getIn().charAt(0) == '{') {
temp.add(stack.pop());
break;
}
else {
temp.add(stack.pop());
}
}
if (!stack.isEmpty()) {
Element tempOwner = stack.lastElement();
if (tempOwner.getType().equals("g")) {
Grade owner = (Grade) tempOwner;
temp.forEach(owner::add);
gradeList.add(owner);
}
else if (tempOwner.getType().equals("c")) {
Clazz owner = (Clazz) tempOwner;
temp.forEach(owner::add);
}
}
colon = colon.substring(0,colon.length()-1);
}
}
}
return gradeList.toArray(new Grade[0]);
}
}