我正在开发一个业余爱好项目,以正确理解封装,可以负责的类和规则。我要求在另一个forum进行代码审查和协助,但我不同意所采用的方法。
我有以下要求:
StudentStatus界面:
public interface StudentStatus {
Collection<String> retrieveDocuments();
StudentType retrieveStatus();
}
public final class Domestic implements StudentStatus {
private final StudentType type;
private final Collection<String> documents;
public Domestic() {
this.type = StudentType.Domestic;
this.documents = Collections.emptyList();
}
@Override
public Collection<String> retrieveDocuments() {
return this.documents;
}
@Override
public StudentType retrieveStatus() {
return type;
}
}
public final class International implements StudentStatus {
private final StudentType type;
private Collection<String> documents;
public International(Collection<String> documents) {
this.type = StudentType.International;
this.documents = Collections.unmodifiableCollection(documents);
}
@Override
public Collection<String> retrieveDocuments() {
return Collections.unmodifiableCollection(documents);
}
@Override
public StudentType retrieveStatus() {
return type;
}
}
学生班:
public final class Student {
//left out constructor and getters for other attributes.
public Collection<String> retrieveDocuments() {
return status.retrieveDocuments();
}
public StudentType retrieveStatus() {
return status.retrieveStatus();
}
public boolean isVerified(StudentType type) {
return this.retrieveStatus() == type;
}
}
大学课程:
public class University {
private final Map<Student,Collection<String>> registeredStudents;
private final StudentType type;
public University()
{
registeredStudents = new HashMap<Student,Collection<String>>();
type = StudentType.International;
}
public void add(Student student){
if (student.isVerified(type)){
registeredStudents.put(student, student.retrieveDocuments());
}else {
//throw an exception or handle error accordingly
}
}
}
在我继续之前,我了解到这是一个真正超过简化的应用程序流程。在现实世界中,在学生注册之前还需要做更多的事情。学生可能必须通过入学考试,并在注册开始前付款。此外,在现实环境中,此信息可能存储在校园员工可以访问的数据库中。
在另一个论坛中,对话进入了正在发布的信息,并给出了方法。
我遇到的问题是,您是否仍需要使用retriveStatus()
或isVerified()
向学生询问他/她的状态,我真的不知道该怎么做任何其他方式。
在现实世界中,大学制定了如上所述的规则,其责任是检查国际学生是否有文件。
当我使用add(Student student)
提出上述方法时,他们表示这不是一个好主意,因为规则可能会发生变化,您将不得不更改学生课程以及大学课程。
然而,在现实世界中,学生非常了解他/她的身份,他/她是否是国内/国际并拥有可以提供给学校的文件。
鉴于上述方法,这样写一个add方法是个好主意吗?有比add方法更好的方法吗?
tl; dr - 如果学生必须遵循大学设定的规则,学生对象如何与大学沟通以获取数据,以便大学可以确保学生对象是否遵守规则而不破坏封装?
答案 0 :(得分:0)
上一篇文章中的对话可能会引导您走向一个良好的方向。最适用的原则是开放/封闭原则。 https://en.wikipedia.org/wiki/Open/closed_principle
不要让自己不得不经常修改一个特定的类或一组类(至少在OO世界中),你知道这个区域会经常变化。该原则同样适用于功能世界,但您的示例是使用OOPL。
很少的手工制作规则引擎对于您提出的问题是一个非常好的解决方案。特别是如果你知道规则在非常固定的输入上流动 - 比如大学和学生。 DocumentsRequiredForInternationalStudents是该体系结构中的规则类 - 只有在该规则本身发生变化时才需要更改。新规则,将会发生很多=添加新类,而不是修改现有规则。
有时你不知道改变的向量,更难做出决定,但如果显而易见的话,不要设计一个系统,你必须由于已知的变化向量而不断地违反开放/关闭。
实现小规则引擎的方法有很多种。一个选项(这是蹩脚的伪代码,因此它占用更少的空间)
interface RegistrationRule
boolean isRegistrationValid(Student student) //might need university too for some rules.
class DocumentsNeededForInternationalStudents implements RegistrationRule
boolean isRegistrationValid(Student student)
// return student.status is international and student has documents, or student status is domestic
// (this rule passes through as valid any domestic students).
class RegistrationRules
// (holds all the rules you will use - kind of a factory)
constructor -> add to static list of rules an instance of all your rules
boolean runRulesForStudent(Student)
//iterate through all rules, call isRegistrationValid, short circuit and return false if one of them false
class University
addStudent(Student student)
if (RegistrationRules.runRules(student).... else
这只是将它放在一起的一种方法,但你可以看到它并不是真正的代码。您有一个接口,每个规则的实现类,以及一个为您应用每个规则的规则引擎类。新规则=新类,修改规则引擎中的构造函数以添加该类的实例,完成。
当规则中所需的属性和行为非常多样化而不是集中在同一小组类中时,这种模式开始变得有点挣扎。
答案 1 :(得分:0)
你说:
在现实世界中,大学制定了如上所述的规则 它的责任是检查国际学生是否有 文档。
这意味着验证责任在于大学(每个大学可能不同)而不是学生。所有学生都可以做的是为大学提供必要的信息来验证。
add
方法应该从retrieveDocuments
获取文档并运行其规则以确定是否允许学生被接受。