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

郊区,城市和越野驾驶声像算法。战略模式可能有助于在这里背景是汽车。