2012-02-14 13 views
5

Digamos que tengo un objeto, Coche, y tiene conjuntos de métodos que son ... dispares? ¿Tal vez tener Blob-como? (como en el antipattern, "blob") Estos métodos operan en conjuntos suficientemente distintos y no se entrecruzan funcionalmente.¿A dónde van los nuevos métodos?

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

Ahora vamos a decir que quería añadir "la conducción fuera de carretera" como uno de los casos que mi objeto coche puede soportar. Si agrego métodos al objeto Car, ¿no es eso lo que lo hace más blando?

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

¿Debo:

A: Subclase de coches. Puedo hacer que OffRoadCar amplíe el objeto Car. ¿Pero qué pasa si Car y OffRoadCar comparten los mismos datos/estado, y solo difieren según los métodos? OffRoadCar solo "actúa" más específicamente que el automóvil, pero no se describe de manera más específica ni tiene campos únicos. Por lo tanto, crear instancias de OffRoadCar no tiene sentido.

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

B: Consumir coche con un método estático. Como OffRoadAdventure-> Embark (Car). Entonces, la clase OffRoadAdventure toma un objeto Car y se sale con la suya.

En C# esto se llamaría un método de extensión.

Supongo que dicho de otra manera es ¿cuál es la solución para el antipatrón Blob? ¿Está subclasificando? ¿Son métodos de extensión?

Además, otra razón por la que quería analizar estos métodos es ¿qué ocurre si su implementación implica algún costo, como la inclusión de otras clases/paquetes? No me gustaría que los usuarios de la clase central paguen constantemente por algo que nunca usarían. Me imagino que hacer el costo explícito para la minoría vale la pena el ahorro para la mayoría. Y hace que el gráfico de dependencia sea más preciso (y no como un blob).

PS - El lenguaje de implementación es Perl.

+0

¿El coche tiene que ser una clase? ¿Podría Car realmente ser un ICar (interfaz)? Sugeriría una ruta de composición sobre herencia. – OnResolve

+0

El automóvil ya es una clase real que está en uso. (en realidad es un artefacto ORM) –

Respuesta

0

Creo que está en el camino correcto. Una solución elegante es tener OffRoadCar heredar del automóvil y anular su método Drive(). De esta manera, se puede decir:

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

Esto llamará al método Drive() se reemplaza en la subclase, y usted no terminar con un tropecientos métodos en un solo "blob". Así es como el método Drive() en OffRoadCar puede verse como:

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

Con Perl que debe tomar un buen vistazo a los alces y los roles.

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

Incluso puede agregar y eliminar roles en el tiempo de ejecución.

+1

¿Cómo soluciona esto el problema de blob? Un rol/interfaz es para clases dispares que cumplen el mismo contrato. –

+1

El problema con el blob es que está transfiriendo toda la funcionalidad del objeto a una única ubicación. El uso de roles le permite dividir las características dispares en módulos de códigos independientes y comprobables y luego aplicarlos a sus objetos según sea necesario. En el tiempo de ejecución, sí, todavía tienes el "objeto de dios blobby", pero en ese momento no estás realmente preocupado por eso, porque los problemas con ese antipattern son re: desarrollo. Dado que puede aplicar roles en tiempo de ejecución, también puede agregar rollo solo la funcionalidad que necesita y no tomar hits de rendimiento innecesarios. – Oesor

+0

Sus ediciones lo han dejado más claro. Pero según algunas limitaciones técnicas, no podemos usar Moose. Sin embargo, entiendo lo que dices. –

0

En lugar de subclasificar la clase Car, puede usar alguna forma de Decorator pattern.

Aquí, la clase base de ORM y los decoradores (digamos OffRoadDecorator) implementan una interfaz común, y el comportamiento de cada decorador se puede agregar dinámicamente a la clase original.

La diferencia clave aquí es que se pueden usar decoradores múltiples en la misma clase Car, y depende de su implementación decir cómo deben interactuar. No hay nada que le impida decorar su clase con el OffRoadDecorator y el SuburbanDecorator, y puede decidir exactamente qué significa eso para el automóvil dentro de los decoradores.

(PS lo siento, no proporciona ninguna ejemplos de código, mi Perl es simplemente horrible un vistazo a this page para algunos otros ejemplos..)

0
No

realmente una respuesta Mark y yo no estoy seguro de hasta qué punto usted quiere entrar en esto, pero podría considerar la idea del Orden de Resolución de Método. En lugar de la primera búsqueda de profundidad estándar para métodos, usar mro le permite realizar una primera búsqueda de amplitud. Consulte this page en CPAN y brian d foy en el artículo Use the C3 method resolution order in multiple inheritance para obtener más información.

0

Suburban, City and Offroad Driving suenan como algoritmos. El patrón de estrategia podría ayudar aquí con Context siendo Auto.

Cuestiones relacionadas