2011-05-15 21 views
5

Me pregunto cuál es la mejor manera en términos de OOP estricto para agregar funcionalidad a tipos incorporados como cadenas o enteros u objetos más complejos (en mi caso, la clase BitSet).La mejor manera de agregar funcionalidad a los tipos incorporados

Para ser más específicos - Tengo dos escenarios:

  1. Adición de un método md5 hash para el objeto String
  2. Adición de métodos de conversión (como fromByteArray() o toInteger()) a la clase BitSet.

Ahora me pregunto cuáles serían las mejores prácticas de aplicación del presente.

Podría, por ejemplo, crear una nueva Clase "BitSetEx" que se extiende desde BitSet y agregar mis métodos. Pero no me gusta la idea, ya que esta nueva clase necesitaría describir el nombre y el sonido "BitSetWithConversionMethods" realmente tonto.

Ahora podría escribir una clase que consta únicamente de métodos estáticos que realizan las conversiones.

Bueno, tengo un montón de ideas pero no sé cuál sería el "mejor" en el sentido de OOP.

Entonces, ¿podría alguien responderme esta pregunta?

Respuesta

3

Hay algunos enfoques aquí:

En primer lugar, se podría llegar a un mejor nombre para la clase extends BitSet. No, BitsetWithConversionMethods no es un buen nombre, pero tal vez algo como ConvertibleBitSet es. ¿Eso transmite la intención y el uso de la clase? Si es así, es un buen nombre. Del mismo modo, puede tener un HashableString (teniendo en cuenta que no puede ampliar String, como señala Anthony en otra respuesta). Este enfoque de denominar clases secundarias con XableY (o XingY, como BufferingPort o SigningEmailSender) a veces puede ser útil para describir la incorporación de un nuevo comportamiento.

Dicho esto, creo que hay un indicio justo en su problema (no poder encontrar un nombre) que tal vez esta no es una buena decisión de diseño, y está tratando de hacer demasiado. En general, es un buen principio de diseño que una clase debe "hacer una cosa". Obviamente, dependiendo del nivel de abstracción, se puede extender para incluir cualquier cosa, pero vale la pena pensar: hacer 'manipular el conjunto/deshacer el estado de varios bits' y 'convertir un patrón de bits a otro formato' contar como uno ¿cosa? Yo diría que (especialmente con la insinuación de que te está costando encontrar un nombre) probablemente sean dos responsabilidades diferentes. Si es así, tener dos clases terminará siendo más limpio, más fácil de mantener (otra regla es que 'una clase debe tener una razón para cambiar'; una clase para manipular + convertir tiene al menos 2 razones para cambiar), más fácil de probar en aislamiento, etc.

Así que sin conocer su diseño, sugeriría tal vez dos clases; en el ejemplo BitSet, tenga un BitSet y (digamos) un BitSetConverter que es responsable de la conversión. Si usted quiere conseguir realmente de lujo, tal vez incluso:

interface BitSetConverter<T> { 
T convert(BitSet in); 
BitSet parse(T in); 
} 

entonces usted podría tener:

BitSetConverter<Integer> intConverter = ...; 
Integer i = intConverter.convert(myBitSet); 
BitSet new = intConverter.parse(12345); 

que en realidad aísla los cambios, hace que cada convertidor diferente comprobable, etc.

(De Por supuesto, una vez que lo hagas, te recomendamos que consultes guava y consideres el uso de Function, por ejemplo, Function<BitSet, Integer> para un caso, y Function<Integer, BitSet> para el otro. Luego obtienes un ecosistema completo de Function -nombre de soporte que puede ser útil)

+0

gracias por esta muy buena respuesta! – tyrondis

3

Me gustaría ir con la clase de ampliación. Eso es realmente lo que estás haciendo, extendiendo la clase actual con algunos métodos adicionales.

En cuanto al nombre: no debe nombrar para las nuevas características, ya que puede agregar más más adelante. Es su clase de BitSet extendida, por lo que BitSetEx ya suena mejor que el BitSetWithConversionMethods que usted propone.

No desea escribir una clase con los métodos estáticos, esto es como la programación de procedimientos en un entorno OOP, y se considera incorrecta. Tiene un objeto que tiene ciertos métodos (como el fromByteArray() que desea hacer) por lo que desea que esos métodos estén en esa clase. Extender es el camino a seguir.

1

Depende. Como señaló nanne, la subclase es una opción. Pero solo algunas veces Las cadenas se declaran definitivas, por lo que no puede crear una subclase. Tiene al menos otras 2 opciones:

1) Use 'encapsulación', es decir, cree una clase MyString que tenga una cadena en la que funcione (en lugar de extender String, que no puede hacer). Básicamente una envoltura alrededor de la cadena que agrega su funcionalidad.

2) Cree una utilidad/ayudante, es decir, una clase con solo métodos estáticos que operen en cadenas. Así que algo como

class OurStringUtil { 
.... 
    public static int getMd5Hash(String string) {...} 
.... 

} 

Tome un vistazo a las cosas Apache StringUtils, se sigue este enfoque; es maravilloso.

1

"La mejor manera" es un poco subjetiva. Y tenga en cuenta que String es una clase final, por lo que no puede extenderla. Dos métodos posibles son escribir envoltorios como StringWrapper(String) con sus métodos adicionales, o algún tipo de clase StringUtils llena de métodos estáticos (ya que Java 5, los métodos estáticos se pueden importar si desea utilizar la clase util directamente).

Cuestiones relacionadas