【问题标题】:Method Caller and Callee, circular class level method invocations方法调用者和被调用者,循环类级方法调用
【发布时间】:2016-08-08 14:39:40
【问题描述】:

两个不同类的方法调用者和被调用者做循环类级别的不同方法调用有什么问题。您将“this”引用作为参数传递给其他一些类实例方法,并且被调用者对作为参数传递的调用者进行进一步的方法邀请。

这样做的一个原因是,在工厂类中,不同的实现需要不同类型的数据,因此您将所需的数据作为多个合约/接口方法并让您的调用者实现它们。如果你只有一个类,实现封装更容易,但是不同的类需要不同的数据集

下面是一个简单的例子,这里 StudentService 调用 MathClassScorer 的 topscorer 方法,该方法又调用 StudentService 的 getStudentList 方法。在复杂的场景中,您可能会调用父调用者的多个方法。

public interface IStudentData { 
    public List<Student> getStudentList();
}

public class StudentService implements IStudentData {
       private List<Student> studentList;

       public String getTop() {
            // Factory returns MathClassScorer
            IScore scorer = ClassScorerFactory.get();
            return scorer.topscorer(someOtherData, this);
       }

       @Override
       public getStudentList() {
          // do something and return studentList;
          return studentList;
       }

}

// IScore contains topscorer method
public class MathClassScorer implements IScore {

     @Override
     public String topscorer(Map someOtherData, IStudentData data) {
         List<Student> studentList = data.getStudentList();
         //do something before and after
         return SOMETHING_AFTER
     }
} 

问题是,上述方法有问题吗?

【问题讨论】:

  • 这样做没有问题。
  • 问题是什么?
  • 问题是,这种方法有什么问题吗?

标签: java oop interface polymorphism higher-order-functions


【解决方案1】:

好吧,恐怕整个 OO 的话题有点争议。但在我看来,上述代码的问题始于类的命名。 IStudentData 不是对象。持有一些数据不是责任,对象需要责任。

那么设计要求IScore对象知道IStudentData的内部数据内容,完全不理会对象。该代码还表明IScore 也需要了解Student 的内部工作原理。

一个好的 OO 设计是对象实际上有责任,并且它们的数据尽可能不可见,理想情况下根本不可见。

因此,在不了解所有细节的情况下,您的对象可能如下所示:

public class Student {
    public boolean isBetterAtMathThan(Student other) {
        ...
    }
}

public class Students { // or StudentRepository
    public Student getBestStudentAtMath() {
        return students.stream().max(toComparator(Student::isBetterAtMathThan)).get();
    }
}

或者,如果您真的想概括几个不同的可比较技能,那么您仍然可以在不暴露学生数据的情况下做到这一点:

public class Students {
    public Student getBestStudentAt(Comparator<Student> skillComparator) {
        return students.stream().max(skillComparator).get();
    }
}

重点是,Student 不应该暴露数据,而是提供操作,或者创建其他可以东西的对象。同样,Students(代码中的服务)不应该公开学生列表,而是应该提供实际事情的方法。

【讨论】:

  • 感谢您的回复,如果只有数学(isBetterAtMathThan),则此方法有效。 ,我可以隐藏我的数据或只传递所需的信息。选择 Factory 的原因是,可以有另一个 Scorer,这可能取决于不同的数据集。
  • 但是,我同意你的观点。但是你能用不同的实现来解决这个问题吗,比如我发布的工厂!!
  • 我必须知道你的目标/要求是什么。通常,所有的“评分”都应该在Student 中完成,因为数据在那里。然后其他班级可以选择需要哪个评分。如果您真的希望它是“可插入的”(仅在您确实需要时才这样做),那么您将必须创建一些不需要从 Student 获取数据的抽象。它可能会在构建“记分器”的过程中提供。
  • >> 它可能在'scorer'的构建过程中提供但是,我们有多个 scorer 实现,每个 scorer 可能有不同的数据依赖关系。
  • 好的。是否可以为有意义的记分员定义一些统一的界面?我的观点是,不是记分员直接从Student 获取()数据,也许Student 可以将“数据”推送到记分员中。
【解决方案2】:

这样做没有问题。这是一种常见的做法,称为Strategy pattern

像这样使用注入是一种非常有用的解耦逻辑技术,允许通过提供模拟对象对每个组件进行单元测试。

【讨论】:

  • 一种策略模式在一个方向上做参考。在这里,我们正在循环方式!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
相关资源
最近更新 更多