OOP设计问题

时间:2010-01-01 18:26:25

标签: php oop

我在PHP中使用OOP相对较新。它对我的代码的组织和维护有很大的帮助,但我希望能够更好地设计我的类并尽可能高效地使用OOP。我已经阅读了Gang of Four Design Patterns一书,但仍然需要一些帮助。在构建了一些小应用程序后,这是我一直在运行的一件事。

假设我正在构建一个跟踪学校注册信息的应用程序。

我目前采用的方法是在一个学生的记录中创建一个名为student的类,以及该类中用于CRUD的方法。似乎合乎逻辑的是,我将为此类创建一个以student_id作为参数的构造函数方法,因此我可以在对象中为所有这些不同的CRUD操作引用它。

但是,随着我继续构建应用程序,我遇到了需要运行返回多个学生的查询的情况。例如,get_all_students_from_grade($grade)get_dropdown_of_all_students()等等。这些方法不仅适用于一个学生,所以我将它们作为student类中的方法似乎很奇怪因为我在实例化对象时考虑了一个student_id。显然我可以通过这种方式使它工作,但似乎我做错了。解决这个问题的最佳方式是什么?

8 个答案:

答案 0 :(得分:4)

student类(属于域类)与其上的操作(业务逻辑或数据访问,根据具体情况)分开,如:

  • student - 域对象仅包含数据
  • student_servicestudent_dao(数据访问对象) - 执行操作

这有时被认为打破了封装,但它是公认的最佳实践。

Here's有关此事的更多信息。从OOP的观点来看,它提供了比封装破坏更多的缺点。因此,尽管它似乎是一种公认​​的做法,但它并不是OOP。

答案 1 :(得分:4)

将其分为两类:

  1. 学生
  2. student_repository
  3. 您的学生班级对于如何以关系方式存储知之甚少。

    $students = student_repository.get_all_students_from_grade($grade)
    

答案 2 :(得分:1)

我并不假装知道“最好的”方式,但这可能有助于以不同方式解决问题。您可以使类代表应用程序和数据库之间的数据接口,而不是让一个类代表单个学生。

这个类将知道如何从数据库中检索一堆(可能是一个)学生行,将它们缓存在本地数组中,允许应用程序浏览缓存的记录,允许对缓存的记录进行修改,以及何时完成,将缓存的修改写回db(通过生成SQL来考虑更改)。

这样,您可以避免为每次更改触发单个SQL语句(您仍然使用一组行),同时提供对单个对象的访问(通过维护缓存中当前位置的索引) ,并允许应用程序提升此“指针”,因为它调用您的类的方法

答案 3 :(得分:1)

始终有一个起点。在你的情况下,你会从学校,班级等那里得到什么。

$class = new Model_Class;

$students = $class->students;

foreach($students as $student)
{
    print $student->name. ' is in class '. $class->name;
}

答案 4 :(得分:1)

我遇到了同样的问题,我猜你在使用MySQL?这是常见的OOP设计挑战之一,因为SQL倾向于压扁所有内容。

我通过以下方式解决了这个问题

1。)创建一个具有三种实例化形式的类,

一个新的

$myStudent = new $Student();

另一个你知道id但需要id数据

的地方
$myStudent = new $Student($student_id);

另一个你已经在关联数组中拥有它的数据

$data = array('id'=13,'name' => 'studentname', 'major' => 'compsci');
$myStudent = new $Student($data['id'], $data);

这允许您创建一个可以从mysql运行查询的工厂类,获取数据的关联数组,然后从该数组数据创建student实例,而无需为每个学生实例访问数据库。

这是这样一个类的构造函数:

public function __construct($id=FALSE, $data=FALSE)
{
    if(!$id) $this->is_new = true;
    else if($id && !$data) $this->get_data_from_db($id);
    else if($id && $data) $this->set_data($data);

}

答案 5 :(得分:0)

您可以使用工厂方法,让工厂决定新学生的ID应该是什么。

当然,这家工厂必须阅读一个数据库,看看在哪里开始索引(基于数据库中有多少学生),你必须决定如何处理被删除的学生(如果这是一个可能性)。

至于你描述的方法,我不明白为什么你必须把它们包括在你的学生班里。你可以但它应该是静态方法而不是成员方法。

答案 6 :(得分:0)

就像尼尔在评论中所说的那样(不确定为什么我们没有给出答案),你也应该有CourseSchool类。您可以在School和课程特定方法(所有具有一定年级的课程中的所有学生等)中使用针对学校的方法(让所有学生达到给定年级,缺少给定天数等)在Course班。

你认为在标准CRUD中你不想给代表个人的类(即Student类)加载自身的倍数是正确的。 另一方面,如果您想要更多ActiveRecord样式的数据加载(这是Ruby on Rails使用的),那么 实际上在Student类本身上创建所有Student加载器方法静态方法。这取决于你想要如何设计它,这在一定程度上取决于你的数据模型将变得多么复杂。

答案 7 :(得分:-1)

你应该在学生身上制作class methods