访问者模式为两个参数 [英] Visitor Pattern for two arguments

查看:136
本文介绍了访问者模式为两个参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个问题陈述:
我们有接口/超级类学生和教师



学生有两个实现/子类,ScienceStudent和PhysicalEducationStudent

教师有ScienceTeacher和PhysicalEducationTeacher。



我们要实现getMeetingPoint(Student s,Teacher t)他们根据学生和老师的类型见面的地方。



例如,
如果它的 ScienceStudent ScienceTeacher 他们在 / strong>
如果 PEStudent PETeacher ,他们会在地面
(如果其 ScienceStudent PETeacher ,反之亦然,他们在自助餐厅

会面



我们可以写一个天真的方法,使用 instanceof 进行检查。但问题是,当老师或学生延长,难以维护时,这变得复杂。
这样的东西:

  public class MeetingPointDecider {

getMeetingPoint(学生,老师t){
if(s instanceof ScienceStudent&
} else if(s instanceof PhysicalEducationStudent& and instance of PhysicalEducationTeacher){
returnGRound;
}



}
}

另一个选择是写一个工厂,它接受一个学生和教师并返回类似MeetingPointDecision [Ground或Lab],但问题仍然存在。
有没有什么好的模式,我们可以使用,我们不必修改现有的类(或最小的修改),当添加一个新的类时,说 instanceof ScienceStudent我们有化学学士,物理学和化学实验室,PhysicsLab。
还有机会添加更多的操作,这些操作在实现中基于
学生和教师类型(Where Visitor是一个选项,但不确定如何使用两个决定类实现)实现不同。



有人可以建议一个很好的方法来实现吗?



谢谢!

解决方案

我将使用地图解决这个问题。关键在于确定老师+学生组合,价值将是会议点。对于关键,我将组合类名。这是解决方案:

  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()) ;
返回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中,地图人口稠密很容易支持未来的课程。


Here is a problem statement: We have interfaces/super classes Student and Teacher

Student has two implementations/sub clasees, ScienceStudent and PhysicalEducationStudent

Teacher has ScienceTeacher and PhysicalEducationTeacher.

We want to implement a method getMeetingPoint(Student s, Teacher t) which returns a place where they meet based on the type of Student and Teacher.

For example, if its a ScienceStudent and ScienceTeacher they meet at Lab if PEStudent and PETeacher they meet on the Ground and if its a ScienceStudent and PETeacher or vice versa, they meet at cafeteria

We can write a naive method, which checks using instanceof. But the problem is, this becomes complex when Teacher or Student gets extended, and tough to maintain. something like this:

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";
        }
        .
        .
        .
    }
}

Another option is writing a factory, which accepts a Student and a Teacher and returns something like MeetingPointDecision [Ground or Lab], but the problem persists. Is there any good pattern we can use, where we do not have to modify existing classes (or minimal modification) when a new class is added, Say instanceof ScienceStudent we have ChemistryStudent, PhysicsStudent and ChemistryLab, PhysicsLab. There is also a chance of adding more actions, which differs in implementation based on the Student and Teacher type ( Where Visitor is an option, but not sure how to implement with two deciding classes)

Can someone please suggest a good way to implement this?

Thanks!

解决方案

I would solve this using a map. The key should identify the teacher + student combination and the value would be the meeting point. for the key I would combine the class names. Here is the solution:

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();
    }
}

The logic part is in the static ctor where the map gets populated. It is easy to support future classes.

这篇关于访问者模式为两个参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆