2012-02-14 89 views
5

比方說,我有一個對象Car,並且它有不同的方法集合?也許變得像Blob一樣? (如在反模式中,「blob」)這些方法運行在足夠明確的集合中,並且在功能上並不真正交叉。新方法去哪裏?

Car 
# methods related to suburban driving 
    ->foo1 
    ->foo2 
# methods related city driving 
    ->bar3 
    ->bar4 

現在讓我們假設我想添加「越野駕駛」爲我的車對象可以支持的案例之一。如果我向Car對象添加方法,是不是讓它更像blob?

Car (augmented) 
# methods related to suburban driving 
    ->foo1 
    ->foo2 
# methods related city driving 
    ->bar3 
    ->bar4 
# methods related off road driving 
    ->blah5 
    ->blah6 

我應該:

答:子類汽車。我可以做一個OffRoadCar擴展Car對象。但是如果Car和OffRoadCar共享相同的數據/狀態,並且只有方法不同,該怎麼辦? OffRoadCar只是比汽車更具體的「行爲」,但沒有更具體的描述,也沒有獨特的領域。因此實例化OffRoadCar是毫無意義的。

OffRoadCar extends Car 
# methods related off road driving 
    ->blah5 
    ->blah6 

B:汽車消費用靜態方法。喜歡OffRoadAdventure->出發(汽車)。因此,OffRoadAdventure類需要一個Car對象,並且有它的方式。

在C#中這將被稱爲擴展方法。

我想換一種方式是Blob反模式的解決方案是什麼?它是繼承嗎?它是擴展方法嗎?

另外,我想孤立這些方法的另一個原因是如果它們的實現會產生一些成本,比如包含其他類/包?我不希望核心課程的用戶經常爲他們永遠不會使用的東西付費。我認爲,爲少數人制定明確的成本是值得大多數人節省的。它使依賴圖更加精確(而不是像blob一樣)。

PS - 實現語言是Perl。

+0

車必須是班嗎? Car可以成爲ICar(接口)嗎?我會建議一個繼承的組合路線。 – OnResolve 2012-02-14 22:28:09

+0

汽車已經是一個真正使用的類。 (它實際上是一個ORM神器) – 2012-02-14 22:30:14

回答

0

我認爲你是在正確的軌道上。一個優雅的解決方案是從Car中繼承OffRoadCar並覆蓋其Drive()方法。這樣一來,你可以說:

Car myCar = new OffRoadCar(); 
myCar.Drive(); 

這將調用子類中重寫Drive()方法,你不要在單一的「斑點」一個極大方法結束。以下是如何在OffRoadCarDrive()方法可能看起來像:

@Override 
public void Drive() 
{ 
/* code */ 
} 
2

用Perl你應該考慮在駝鹿和角色好好看看。

package Suburban; 
use Moose::Role; 

requires 'wheels'; 

sub 'foo1' { 
    ... 
} 


sub 'foo2' { 
    ... 
} 

package City; 
use Moose::Role; 

requires 'wheels'; 

sub 'bar3' { 
    ... 
} 


sub 'bar4' { 
    ... 
} 

package Offroad; 
use Moose::Role; 

requires 'wheels'; 

sub 'blah5' { 
    ... 
} 


sub 'blah6' { 
    ... 
} 

package UltraCar; 
use Moose; 

with qw/ Offroad City Suburban /; 
has 'wheels' => (is => 'rw', isa => 'Int', default => 4); 

package RentalCar; 
use Moose; 

with qw/ City Suburban /; 
has 'wheels' => (is => 'rw', isa => 'Int', default => 4); 

package Tricycle; 
use Moose; 

with qw/ Offroad /; 
has 'wheels' => (is => 'rw', isa => 'Int', default => 3); 

您甚至可以在運行時添加和刪除角色。

+1

這是如何解決blob問題的?角色/接口適用於實現同一合同的不同類。 – 2012-02-14 22:54:06

+1

blob的問題在於您將對象的所有功能都轉換爲單個位置。使用角色可以將不同的功能分解爲單獨的,可測試的代碼模塊,然後根據需要將它們應用到對象中。在運行時,是的,你仍然有'blobby god object',但是那時你並不擔心這個,因爲反模式的問題是re:開發。由於您可以在運行時應用角色,因此您還可以僅添加需要的功能,而不會採取不必要的性能命中。 – Oesor 2012-02-14 23:01:49

+0

您的編輯更清晰。但是根據一些技術限制,我們不能使用Moose。我明白你的意思。 – 2012-02-14 23:08:16

0

而不是繼承Car類的子類,可以使用某種形式的Decorator pattern

這裏,基本的ORM類和裝飾器(比如OffRoadDecorator)實現了一些通用的接口,並且每個裝飾器的行爲都可以動態添加到原始類中。

這裏的關鍵區別在於,多個裝飾器可以用在同一個Car類中,並且由您的實現來決定這些應該如何交互。沒有什麼可以阻止你使用OffRoadDecorator以及SuburbanDecorator來裝飾你的班級,並且你可以準確地決定裝飾者對賽車的意義。

(PS對不起,我不提供任何代碼示例,我的Perl簡直太可怕了看一看this page一些其他的例子。)

0

郊區,城市和越野駕駛聲像算法。戰略模式可能有助於在這裏背景是汽車。