新方法在哪里?

时间:2012-02-14 22:25:21

标签: perl oop design-patterns anti-patterns

假设我有一个对象,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

我应该:

答: Subclass Car 。我可以制作一个OffRoadCar扩展Car对象。但是如果Car和OffRoadCar共享相同的数据/状态,并且只是方法不同呢? OffRoadCar只比汽车更具体“行动”,但没有更具体的描述,也没有独特的领域。因此实例化OffRoadCar毫无意义。

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

B:使用静态方法消耗汽车。喜欢OffRoadAdventure-> Embark(Car)。因此,OffRoadAdventure类接受一个Car对象并使用它。

在C#中,这将被称为扩展方法。

我想另一种方法是 Blob反模式的解决方案是什么?是子类吗?是扩展方法吗?

另外,我想要解决这些方法的另一个原因是,如果它们的实现会产生一些成本,比如包含其他类/包?我不希望核心类的用户经常为他们永远不会使用的东西买单。我认为让少数人明白成本对大多数人来说是值得的。它使依赖图更精确(而不是像blob一样)。

PS - 实现语言是Perl。

5 个答案:

答案 0 :(得分:2)

使用Perl,你应该好好看看Moose和角色。

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 :(得分:0)

我认为你走在正确的轨道上。一个优雅的解决方案是让OffRoadCar从Car继承并覆盖其Drive()方法。这样,你可以说:

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

这将在子类中调用重写的Drive()方法,并且您不会在单个“blob”中使用大量方法。以下是Drive()OffRoadCar方法的显示方式:

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

答案 2 :(得分:0)

您可以使用某种形式的Decorator pattern,而不是对Car类进行子类化。

这里,基础ORM类和装饰器(比如OffRoadDecorator)实现了一些通用接口,每个装饰器的行为可以动态地添加到原始类中。

这里的关键区别在于,可以在同一个Car类上使用多个装饰器,并且由您的实现来说明它们应该如何交互。没有什么可以阻止你使用OffRoadDecoratorSuburbanDecorator装饰你的课程,你可以确定装饰师对汽车的确切含义。

(P.S。抱歉,我没有提供任何代码示例;我的Perl非常糟糕。请查看this page以获取其他一些示例。)

答案 3 :(得分:0)

不是真的答案马克,我不确定你想深入研究这个问题,但你可以研究一下方法解决方案的概念。使用mro允许您执行广度优先搜索,而不是标准深度优先搜索方法。有关详情,请参阅有关CPAN的this pagebrian d foy的文章Use the C3 method resolution order in multiple inheritance

答案 4 :(得分:0)

郊区,城市和越野驾驶听起来像算法。策略模式可能有助于将Context作为Car。