访问者模式的两个参数
这是一个问题陈述:我们有接口/超级班的学生和老师
学生有两个实施/分类,ScienceStudent和PhysicalEducationStudent
教师有科学教师和物理教育教师。
我们想要实现一种方法getMeetingPoint(Student,Teacher t),它根据学生和教师的类型返回他们见面的地方。
举例来说,如果其ScienceStudent和ScienceTeacher他们在实验室会面,如果PEStudent和体育教师 ,他们在地面上,如果其ScienceStudent和体育教师或反之亦然见面时,他们在餐厅见面
我们可以编写一个简单的方法,使用instanceof
进行检查。 但问题是,当教师或学生得到延伸并且难以维护时,这变得复杂。 像这样的东西:
public class MeetingPointDecider {
getMeetingPoint(Student s,Teacher t) {
if(s instanceof ScienceStudent && t instanceof ScienceTeacher) {
return "Lab";
} else if (s instanceof PhysicalEducationStudent && t instanceof PhysicalEducationTeacher) {
return "GRound";
}
.
.
.
}
}
另一种选择是编写一个工厂,该工厂接受学生和教师并返回类似于MeetingPointDecision [地面或实验室]的东西,但问题依然存在。 有什么好的模式可以使用,当我们添加一个新类时,我们不需要修改现有的类(或者最小的修改)。比如说Science的instanceof
我们有ChemistryStudent,PhysicsStudent和ChemistryLab,PhysicsLab。 还可以添加更多的动作,这些动作在学生和教师类型的实现方面有所不同(“访问者”是一个选项,但不确定如何使用两个决策类实现)
有人可以建议一个好的方法来实现这一点?
谢谢!
我会用地图解决这个问题。 关键应该确定教师与学生的组合,价值就是交汇点。 对于关键我会结合类名。 解决方案如下:
public class MeetingPointDecider
{
public enum MeetingPoint { Ground, Lab, Cafeteria }
private static MeetingPoint defaultmp = MeetingPoint.Cafeteria;
private static Map<String, MeetingPoint> studentTeacherCombinations = new HashMap<>();
static {
studentTeacherCombinations.put(getMapKey(ScienceTeacher.class, ScienceStudent.class), MeetingPoint.Lab);
studentTeacherCombinations.put(getMapKey(PETeacher.class , PEStudent.class) , MeetingPoint.Ground);
}
public static MeetingPoint getMeetingPoint(Student s,Teacher t)
{
String mapKey = getMapKey(t.getClass(), s.getClass());
return studentTeacherCombinations.containsKey(mapKey) ?
studentTeacherCombinations.get(mapKey) : defaultmp;
}
private static String getMapKey (Class<? extends Teacher> tCls, Class<? extends Student> sCls)
{
return tCls.getName() + "_" + sCls.getName();
}
}
逻辑部分位于地图填充的静态ctor中。 支持未来的课程很容易。
这是一个有趣的话题,因为最近Eric Lippert撰写了一篇文章来讨论这个问题。 它分为五个部分:
代码是用C#语言编写的,但我认为从Java的角度来看应该是可以理解的,至少。
总之,你不会得到更好的结果与工厂或访客模式。 您的MeetingPointDecider
实施已经按计划进行。 如果您仍然需要一些硬编码或映射较少的东西,请尝试sharonbn的解决方案或类似方法。
或者如果你需要可扩展的规则,你可以尝试类似Decorator模式的东西:
public class MeetingPointDecider {
// the rules, you can add/construct it the way you want
Iterable<MeetingPointDeciderRule> rules;
string defaultValue;
getMeetingPoint(Student s,Teacher t) {
string result;
for(MeetingPointDeciderRule rule : rules){
result = rule.getMeetingPoint(s, t);
//check whether the result is valid and not null
//if valid, return result
}
//if not valid, return default value
return defaultValue;
}
}
//this can be easily extended
public abstract class MeetingPointDeciderRule {
getMeetingPoint(Student s,Teacher t) {
}
}
最后但不推荐,但如果您仍然需要灵活性,您可以尝试运行时编译该类并将其用作规则引擎。 但不推荐。
注意:我没有回答原来的问题,因此社区维基答案。 如果此答案格式错误,我会将其删除。
如果向接口(学生和教师)添加getMeetingKeyPart()方法并实施以返回每个学生和教师实施的特定关键部分,会怎么样?
例如ScienceStudent返回“ScienceStudent”,ScienceTeacher返回“ScienceTeacher”。
然后,您可以定义一个.properties文件,其中为任何所需的组合键定义了会议点。 例如
ScienceStudent-ScienceTeacher=Lab
PhysicalEducationStudent-PhysicalEducationTeacher=Ground
...
如果没有匹配的组合键,则返回“自助餐厅”
链接地址: http://www.djcxy.com/p/26473.html