2010-01-01 105 views
6

我在PHP中使用OOP比較新。這對我的代碼的組織和維護非常有幫助,但我希望在設計我的類和儘可能高效地使用OOP方面做得更好。我讀過四本綱要設計模式書,但仍需要一些幫助。在構建一些小應用程序之後,我繼續運行一件事。OOP設計問題

假設我正在構建一個跟蹤學校註冊信息的應用程序。

我目前處理這個問題的方法是在一個單獨的學生記錄中創建一個名爲student的類,以及該類中針對CRUD的方法。看起來合乎邏輯的是,我將這個類的構造方法以student_id作爲參數,所以我可以從對象中爲所有這些不同的CRUD操作引用它。

但是,當我繼續構建應用程序時,我遇到了需要運行返回多個學生的查詢的情況。例如,get_all_students_from_grade($grade),10等等。這些方法並不適用於一個學生,所以看起來很奇怪,我會把它們作爲我的student類中的方法,因爲我想到了一個student_id實例化對象。很明顯,我可以通過這種方式來實現這一目標,但看起來我「做錯了」。解決這個問題的最好方法是什麼?

+2

如果你有「學生」,你可能也想「當然」和「學校」,這似乎是「get_students」方法好位置。 – 2010-01-01 18:28:32

回答

4

分離student類(這是一個域類)從操作上它(業務邏輯或數據訪問,根據情況),如:

  • student - 域對象只包含數據
  • student_servicestudent_dao(數據訪問對象) - 執行操作

這有時認爲是破壞封裝,但它是一個公認的最佳PRAC蒂斯。

Here's有關此事的更多信息。從OOP的觀點來看,它比封裝的破裂提供了更多的缺點。所以即使它看起來是一種公認​​的做法,它也不是OOP。

+0

這聽起來像是最簡單的方法。你能描述/提供描述「域」類/對象概念的鏈接嗎?我無法用Google快速找到任何內容。 – Matthew 2010-01-01 18:43:54

+0

@Matthew:在Martin Fowler的書(應用UML和模式)中有很好的描述,但你可以在這裏有一個想法: http://martinfowler.com/eaaCatalog/domainModel.html 和這裏 http:// en。 wikipedia.org/wiki/Domain_model – 2010-01-01 18:57:47

+0

@Matthew:如果你想爲SQL表提供面向對象的接口,那麼我建議使用類似Active Records等的東西。控制器類可以使用這些對象進行CRUD操作(它們也支持手動SQL查詢)。 你的想法是正確的。我只是認爲你不應該再次發明輪子,但對於所有非數據庫操作,你應該使用@Bozho正在討論的方法。另一方面,來自我的問題很快;爲什麼人們不會使用更多的控制器類的靜態類方法? – 2010-01-01 19:55:04

-1

你應該讓他們在學生class methods

+0

我不明白這一個downvotes。 – 2010-03-29 05:38:43

4

打破它分爲兩類:

  1. 學生
  2. student_repository

您的學生類並不知道它是如何關聯存儲。

$students = student_repository.get_all_students_from_grade($grade) 
0

您可以使用工廠方法,讓工廠決定新學生的ID應該是什麼。

當然,這家工廠必須讀取數據庫才能看到索引的起始位置(根據數據庫中有多少學生),並且您必須決定如何處理已刪除的學生(如果這是一個潛在可能)。

至於你所描述的方法,我不明白爲什麼你必須包括在你的學生班。你可以但它應該是一個靜態方法,而不是一個成員方法。

1

我不假裝知道「最好」的方式,但它可能有助於以不同的方式解決問題。不要讓一個類代表一個學生,你可以讓這個類代表你的應用程序和數據庫之間的數據接口。

這個類將知道如何從數據庫中檢索一堆(可能是一個)學生行,將它們緩存在本地數組中,允許應用程序瀏覽緩存記錄,允許修改緩存記錄,以及何時完成後,將緩存的修改寫回數據庫(通過生成SQL來說明更改)。

這樣,您可以避免爲每個更改啓動單個SQL狀態(您仍然使用一組行),並且同時提供對各個對象的訪問權限(通過維護指向當前位置的索引緩存,並允許這個「指針」由應用程序進階,因爲它調用你的類的方法)

0

像尼爾在他的評論中說的(不知道爲什麼我們沒有答案),你應該可能也有CourseSchool類。您可以在Course班級中使用School以及特定課程方法(具有某一年級的課程中的所有學生等),針對特定學校的方法(讓所有學生處於特定等級,缺勤天數等) 。

你認爲在標準CRUD中你不想給一個代表個人的班級(即Student班級)加載其自身倍數的責任是正確的。 在另一方面,如果你要更多的ActiveRecord風格數據加載(這是Ruby on Rails的員工),那麼你實際上使所有Student加載器方法上Student類本身的靜態方法。這取決於你想如何設計它,這部分取決於你的數據模型將變得多麼複雜。

1

總是有一個起點。就你而言,這將是你從學生(如學校,班級等)獲得什麼。

$class = new Model_Class; 

$students = $class->students; 

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

我來過這個相同的問題,我猜你正在使用MySQL嗎?這是常見的面向對象設計挑戰之一,因爲SQL傾向於將所有東西都弄平。

我這樣做解決了這個以下

1)作出有三種形式實例化一個類,

之一,它是新的

$myStudent = new $Student(); 

另一個地方,你知道的ID但需要ID數據

$myStudent = new $Student($student_id); 

和另一個你已經有它的dat一個關聯數組

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

這可以讓你做,可以從MySQL運行查詢一個工廠類,獲取數據的關聯數組,然後創建數組數據學生的情況下,沒有擊中數據庫每個學生的實例。

這裏是這樣一類的構造函數:

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

} 
+0

這是一個有趣的方法,但如果你總是知道該期待什麼,那麼與班級一起工作會不會更容易?如果我在代碼中看到對象,我就無法分辨出它是什麼樣的學生對象,而沒有找到實例化的那一行。 – Matthew 2010-01-01 18:53:47

+0

我不確定我是否理解你的問題,在上面的例子中他們都是一樣的,哦,我忘了顯示可選的參數,我會添加到我的解釋。 – 2010-01-01 18:58:16

+0

我明白你現在在說什麼。但是在所有三個例子中,這個班級都是作爲一名學生實例化的,而我遇到的問題是將一名學生的CRUD活動與涉及多名學生的方法區分開來。 – Matthew 2010-01-01 19:02:29