2015-09-04 60 views
1

在大多數定義中,POJO(Plain Old Java Object)是具有屬性的對象,只有getter/setters。有些人將這些DTO命名。所以基本上他們就是我喜歡稱之爲'數據類'的東西。無論名字是什麼,我知道有這些類型的對象,它只有getter/setter。這些通常用於開發多層MVC Web應用程序 - 這些對象將通過不同的層傳遞。是POJO反對象取向(OO)?

也許我的問題有點朝向自己 - 但這是純粹的面向對象嗎? 我決定找出答案,即什麼是對的,什麼是錯的?

......因爲,我已經提出了學習,即OOP是關於通過交互將真實場景/情景建模爲對象的。對象本身封裝了作用於這些數據的數據和行爲。 - 在我看來,只有getters/setters的對象不適合這個定義。此外,數據類是不好的(代碼味) - 這是我在大學教過的東西。

+0

因此,而不是數據類,你寧願使用什麼?一張地圖? – Makoto

+0

呃,這取決於我猜的問題。但是我認爲地圖是完全可以接受的。沒有? – SoftwareDeveloper

+4

使用對象來表示意圖並封裝信息。 – Makoto

回答

1

沒有像純粹的面向對象的東西。多年來人們與OO合作的方式發生了變化。

我更傾向於將行爲添加到我的類型(https://en.wikipedia.org/wiki/Domain-driven_design)。如果您將某個類型視爲一個數據容器(POJO),則需要將該行爲放在某處。通常稱爲xxxService。這是一個額外的間接水平,只是爲了做一些可能成爲「POJO」核心業務的東西。

在編寫一些更多的代碼之後,您可能最終需要在其他地方使用此功能。現在你需要將這個提取給一些你可以分享的助手。這意味着你會有2個服務調用相同的方法來處理你的POJO。另一個間接水平增加了。

但這是做到這一點的一種方式。我已經參與了很多項目,很多開發人員對setter/getter的東西感覺更加舒適。如果你有一支感覺更熟練的隊伍,那爲什麼不呢。 它不會殺死該項目,但你必須每天都看到;)

1

您可能會將POJO與Beans混合在一起,並且存在顯着差異。

  • 甲豆是具有繞其getter/setter方法的命名(get___任何非布爾值,和用於is___一個布爾)強約定的類。 POJO沒有。
  • 一個bean在其中有一個無參數構造函數,它可以實現Serializable。 POJO可能也不會做。
  • 一個bean的字段必須是私有的。 POJO的字段可能不是。

現在,問題:如果做得好,POJO可以正確地封裝數據並以OO方式運行。你將在一個特定的對象上運行,而不是暴露它的內部,你不得不擺弄它(例如,如果你只有一個地圖可以使用;如果你封裝了那個地圖,它會更好些更好在一個對象中)。

當它不會以面向對象的方式行事時,POJO承擔的責任應該超過應有的。

1

當你說數據類時,我假設你正在談論類似於C和C++中struct的結構,它只包含數據。就我個人而言,我認爲數據類不是壞的,也不是代碼味道。

數據類允許您將屬於同一實體的多個屬性組合在一起。例如:

class Monster{ 
    String name; 
    int hp; 
    int damage; 
} 

通過上述,您可以在參數周圍傳遞整個怪物對象:

public void attack(Monster m){ 
    //Attack monster 
} 

代替:

public void attack (String name, int hp, int damage){ 
    //Attack monster 
} 

如果它是壞的,爲什麼人們偶爾會使用struct而不是C++中的類?

+0

我自己不是C++開發人員,我自己是Java開發人員。但我在船上提出你的意見。有一定的歡迎。非常好的思想點。 – SoftwareDeveloper

+1

@SoftwareDeveloper當然。此外,當我們談論面向對象的時候,它提醒我們像封裝,繼承和多態。即使它只是一個只有getter和setter的類,它仍然服從上述3個屬性,它仍然符合OOP概念。 – user3437460

0

POJO和XXService是壞主意!任何動作(方法)都屬於一個對象。

OK,只是看一個樣本,它是人的簡單的動作:

Class People { 
    string name; 
} 

Class PeopleService{ 
    public void pee(People people){ 
     System.out.print(people.name + " relax..."); 
    } 
} 

啊哈,現在我們需要擴展它... ...,我們知道男人和女人之間的一些差異

class Man extends People{} 

class Woman extends People{} 

如果只有一項服務,你應該寫:

Class PeopleService { 
    public void pee(People people){ 
     if(people instanceof Man)//if ... and if ... 
      System.out.println("stand up"); 
     if(people instanceof Woman) 
      System.out.println("sit down"); 
     System.out.print(people.name + " relax..."); 
    } 
} 

如果你擴展你的服務:

Class ManService extends PeopleService { 
    @Override 
    public void pee(People people){ 
     if(people instanceof Man) 
      System.out.println("stand up"); 
     super.pee(); 
    } 
} 

Class WomanService extends PeopleService { 
    @Override 
    public void pee(People people){ 
     if(people instanceof woman) //you must check it 
      System.out.println("sit down"); 
     super.pee(); 
    } 
} 

//maybe wrong when anyone call these service 
... 
People p = new Woman(); 
... 
manService.pee(p);//you can't stop it! 

比我們可以寫一個serviceFactory ...,太瘋狂了! 但OOP代碼,人是域對象,它是完美的!

Class People { 

    String name; 

    public void pee(){ 
     System.out.print(name + " relax..."); 
    } 
} 

Class Man extends People { 
    @Override 
    public void pee() { 
     System.out.println("stand up"); 
     super.pee(); 
    } 
} 

Class Woman extends People { 
    @Override 
    public void pee() { 
     System.out.println("sit down"); 
     super.pee(); 
    } 
} 

//we call it now, don't care about details 
... 
People p1 = new Man(); 
People p2 = new Woman(); 
p1.pee(); 
p2.pee(); 

想到OOP基本上!大部分程序員都忘記了!

1

我意識到這個問題已經有一年了。但是我覺得POJO的jist沒有被其他答案解決。

回答你的問題:「是POJO反對象取向(OO)?」。

不,是的。

簡單anwser解釋

沒有,因爲OO約爲建模概念,你需要的。一個POJO就是這樣做的。它將一些信息捆綁到一個對象中。

是的,因爲POJO違反OO中使用了一些原則。如tell don't ask-原則。

詳細的回答解釋

POJO的只不過是數據的容器。你不告訴POJO做任何事情。它只是一些信息的表示。因此,你問它的當前狀態。這意味着你違反了tell dont ask

然而,這在一點上是不可避免的。就像函數式編程語言引入IO定義來指定函數不是「純」的。你將不得不您整潔的小OO泡程序要問的東西到外面去.. urhg ..外面..

包裝一下你的POJO的

這就是爲什麼我換POJO的模型中(命名取決於根據你的喜好,我稱他們爲模特)。你可以用擴展名(比如Klaus在他的回答中)或者組合(我更喜歡)來做到這一點。哪一個讓你感到癢癢。

POJO定義了一個真實/抽象的數據源(你並不總是模擬真實的東西)。

實施告知不要問

這隨後被傳遞到的DataModel這是負責操縱POJO。

它通過被「告知」來操縱POJO來做到這一點。我這樣做的原因是因爲有時POJO包含類型信息。 因此,直接操作POJO通常會導致某些類必須檢查POJO的鍵入。

經常做這樣的事情:

if(POJO.type == "something"){ 
    this.doSmthWithPOJO(); 
} 

現在,你可能最終得到一大堆POJO的具有不同的類型。因爲在你的POJO類型的信息意味着你必須做一些事情一點點不同

if(POJO.type == "something"){ 
     this.doSomethingWithPOJO(POJO); 
} 
else if (POJO.type == "something else") 
{ 
    this.doSomethingElseWithPOJO(POJO); 
} 
else if(POJO.type == "something else entirely") 
{ 
    this.doSomethingElseEntirelyWithPOJO(POJO); 
} 
else{ 
    this.print("This is starting to get ugly..."); 
} 

你這樣做:在這種情況下,你可能最終得到這樣的事情。使用可調用函數的DataModel內部的POJO可以讓您做更乾淨的事情。在你的課堂之外移動負責任的操縱或類型檢查。

POJOTypeDataModel model = new POJOTypeDataModel(POJO); 

然後上面的If-elseif-else語句因爲簡單得多。

model.doSomething(); 

正如我上面提到的,你將不得不在一個問題上詢問「POJO.type」。 我這樣做,當我第一次需要的數據源。數據源調用返回POJO。你檢查它的類型並返回一個DataModel而不是POJO。

重要的是要強調你只需要檢查一次POJO的類型!目前你正在檢索/創建POJO幷包裝它。

如果POJO沒有包裝或專門打印,您將不得不向POJO詢問更多的類型。這混亂了使用POJO的類的原始意圖。 它也擺脫了一大堆if語句。

此外,你也鼓勵使用抽象而不是特定類型。

總之

做上述可幫助您:

  1. 保持外部之外。由於POJO往往是一個數據源。
  2. 儘可能地堅持tell don't ask
  3. 鼓勵使用抽象而不是具體類型(不能比POJO更具體)。
  4. 書寫清理器(你不需要在任何地方進行類型檢查)和更容易理解的代碼(人們在理解程序代碼的大塊方面非常糟糕)。
  5. 最終包裝可以幫助您避免更改您的代碼。正如你可能在你的代碼中檢查POJO的全部內容(參見if示例)。現在你簡單的在DataModel上調用一個函數,它知道該怎麼做。

回到簡單的答案

不能避免索要信息的POJO。但它對建模數據源非常完美。

因此,封裝它並使用抽象來調用DataModel限制了一些核心面向對象原則的違反,並且它使得整潔的代碼更加簡單。