usados software programacion patrones orientado orientada objetos mas ejemplos diseño clases design architecture oop class-design

design - software - ¿Cómo diseñas proyectos orientados a objetos?



programacion orientada a objetos ejemplos (23)

  1. estudiar y masterizar patrones de diseño.
  2. A continuación, aprenda sobre el Diseño Dirigido por Dominio
  3. Después de eso, aprende la recopilación de requisitos.

Tomé un curso de OOD hace algunos semestres y aprendí mucho de él; como escribir UML y traducir documentos de requisitos en objetos y clases. También aprendimos los diagramas de secuencia, pero de alguna manera me perdí la clase o algo así, no se quedaron conmigo.

  1. Usted sabe sobre el paso 3. Necesita dominarlo. Quiero decir, a través de mucha práctica para que se convierta en tu segunda naturaleza. Eso es porque el método que aprendes, es simplemente contra la forma en que solíamos tener. Así que necesitas realmente dominarlo. De lo contrario, siempre volverá a su forma original de hacer las cosas. Esto es de alguna manera como Test Driven Process, donde muchos desarrolladores de Java lo abandonaron después de varios intentos. A menos que lo dominen completamente, de lo contrario es solo una carga para ellos.

  2. Escribir casos de uso, especialmente para cursos alternativos. El curso alternativo ocupa más del 50% de nuestro tiempo de desarrollo. Normalmente, cuando tu PM te asigna una tarea, por ejemplo, crea un sistema de inicio de sesión, él pensará que es sencillo, puedes tomarte 1 día para finalizarlo. Pero nunca tiene en cuenta que debe considerar, 1. qué pasa si la clave de usuario tiene una contraseña incorrecta, 2. qué pasa si la clave de usuario tiene una contraseña incorrecta 3 veces, 3. qué sucede si el usuario no ingresa el nombre de usuario, etc. Debe enumerarlos y mostrárselo a su primer ministro. Pídale que vuelva a programar la fecha límite.

Estoy trabajando en un proyecto grande (para mí) que tendrá muchas clases y tendrá que ser extensible, pero no estoy seguro de cómo planificar mi programa y de cómo deben interactuar las clases.

Tomé un curso de OOD hace algunos semestres y aprendí mucho de él; como escribir UML y traducir documentos de requisitos en objetos y clases. También aprendimos los diagramas de secuencia, pero de alguna manera me perdí la clase o algo así, no se quedaron conmigo.

Con proyectos anteriores, he intentado usar métodos que aprendí en el curso, pero por lo general terminan con un código que tan pronto como puedo decir "sí, se parece a lo que tenía en mente", no tengo ningún deseo de profundizar en el lodo para agregar nuevas características.

Tengo una copia del Código Completo de Steve McConnell, que continuamente escucho es increíble, aquí y en otros lugares. Leí el capítulo sobre diseño y no parecía salir con la información que buscaba. Sé que dice que no es un proceso de corte y secado, que se basa principalmente en heurísticas, pero parece que no puedo tomar toda su información y aplicarla a mis proyectos.

Entonces, ¿ qué hacen las cosas durante la fase de diseño de alto nivel (antes de comenzar la programación) para determinar cuáles son las clases que necesita (especialmente las que no se basan en ningún "objeto del mundo real") y cómo interactúan entre sí ?

Específicamente estoy interesado en cuales son los métodos que usas? ¿Cuál es el proceso que sigue que usualmente ofrece un diseño bueno y limpio que representará el producto final?


A menudo se repite pero es completamente cierto: entienda sus datos.

Para la POO, sus clases deben describir piezas importantes de información y cómo interactúan.

Si tiene un modelo mental que describe bien el comportamiento y el tiempo de vida de los datos, tendrá un paseo fácil en el diseño de sus clases.

Esto es simplemente una extensión de: Sepa exactamente lo que está tratando de hacer.



Creo que la respuesta aquí debería ser muy diferente dependiendo de la experiencia del mundo real del tipo que pregunta.

Si tiene solo uno o dos años de experiencia laboral, debe ir al punto que es: ¿cómo llega al punto en que realmente conoce sus datos y entiende exactamente lo que está tratando de hacer?

Sí, si ha estado trabajando en el mundo real más de 5 años, entonces elegiría cualquiera de los muchos modelos o técnicas de procesos de desarrollo de software.

Pero no obtienes experiencia leyendo solo libros. Debes aprender trabajando en un buen grupo bajo un buen liderazgo.

Si eso no es posible, entonces debes hacerlo solo. Comience a iterar codificando un trozo de código probablemente muy desagradable, aprendiendo sus errores, eliminándolo todo, codificando uno mejor y así sucesivamente.

Aprenderás mucho sobre tu código base. Las herramientas son herramientas, no te enseñarán nada.


Cuando tuve la oportunidad, normalmente uso lo que llamo la "regla de las tres iteraciones".

En la primera iteración (o inicio), concibo el diseño general de la aplicación de acuerdo con los objetos del modelo, los algoritmos y las direcciones futuras esperadas ( realmente esperadas, no esperadas). No escribo documentos de diseño, pero si tengo que coordinar a varias personas, se necesita un bosquejo aproximado del procedimiento, junto con un análisis de las dependencias y una estimación del tiempo necesario. Intente mantener esta fase al mínimo si, como yo, prefiere un método más ágil. Hay casos en los que se necesita una fase de diseño sólida, en particular cuando todo es conocido y verdadero acerca de la lógica de su programa, y ​​si planea tener muchas interacciones entre las funciones de su código. En este caso, los casos de uso o las historias de usuario son una buena idea de alto nivel, en particular para las aplicaciones GUI. Para las aplicaciones de línea de comandos, y en bibliotecas en particular, intente escribir "historias de programas" en las que codifique contra la biblioteca que tiene que desarrollar y verifique cómo se ve. Estos programas se convertirán en pruebas funcionales de su biblioteca cuando se completen.

Después de esta primera iteración, comprenderá mejor cómo interactúan las cosas, resolvió los detalles y los puntos difíciles, resolvió problemas con un parche de cinta adhesiva. Está listo para aprovechar esta experiencia para mejorar, limpiar, pulir, dividir lo que era demasiado grande, fusionar lo que estaba demasiado fragmentado, definir y usar patrones de diseño, analizar cuellos de botella de rendimiento y problemas de seguridad no triviales. En general, todos estos cambios tendrán un gran impacto en las pruebas unitarias que escribió, pero no en las pruebas funcionales.

Cuando complete esta segunda iteración, tendrá una pequeña joya, bien probada, bien documentada y bien diseñada. Ahora que tiene la experiencia y el código para hacer la tercera iteración, extienda. Agregará nuevas funciones y casos de uso para mejorar su aplicación. Encontrará puntos difíciles y finalmente ingresará a una cuarta iteración que es análoga a la segunda. Enjuague y repita.

Este es mi enfoque general para el diseño de software. Es similar al diseño en espiral, con iteraciones cortas de tres meses y elementos de desarrollo Agile, que le permite conocer los problemas y conocer su software y su campo de aplicación. Por supuesto, es una cuestión de escalabilidad, por lo que si la aplicación es tan grande que involucra a cientos de desarrolladores, las cosas son un poco más complejas que esto, pero al final creo que la idea es siempre la misma, divide et impera .

Así que resumiendo:

  1. En la iteración uno, puedes saborearlo y aprender
  2. En la iteración dos, usted limpia su producto y lo prepara para el futuro.
  3. En la iteración tres, agrega nuevas características y aprende más
  4. goto 2

Durante mis aventuras de diseñar estructuras de clase, he notado que es muy útil comenzar a escribir algunos pseudocódigos. Eso significa que empiezo por "escribir" algunos fragmentos generales del código de la aplicación en un nivel superior, juego con él y descubro los elementos que aparecen, de hecho, los elementos que yo, como programador, me gustaría usar. Es un muy buen punto de partida para diseñar la estructura general de los módulos y sus interacciones. Después de algunas iteraciones, toda la estructura comienza a parecerse más a un sistema completo de clases. Es una forma muy flexible de diseñar partes de código. Puedes llamarlo un diseño orientado a programadores.


El problema con los proyectos grandes es que no puede supervisar todas las interacciones entre componentes. Por eso es importante reducir la complejidad del proyecto. Los diagramas de clase y de secuencia son demasiado detallados para esta fase de diseño.

Primero intenta pensar desde un nivel de abstracción más alto. Piense en los componentes principales y sus responsabilidades (su interfaz con otros componentes), observe algunos patrones arquitectónicos en busca de inspiración (no, no patrones de diseño, ¡estos son niveles demasiado bajos! MVC y Multi-Tier son ejemplos de patrones arquitectónicos). Para proyectos razonablemente grandes, esta vista debe tener alrededor de 3-5 componentes.

Solo entonces amplías un determinado componente y tratas de diseñar eso. Ahora estamos en el nivel de patrones de diseño y diagramas de clase. Intente enfocarse en esta parte del proyecto, si encuentra que necesita agregar una responsabilidad a uno de los otros componentes, simplemente agréguelo a su documentación / lista de tareas pendientes. No pierda el tiempo pensando en las implicaciones que en este punto cambian demasiado rápido, revise cuando el diseño es más sólido.

No es necesario que diseñe completamente cada componente en este punto, aunque es probable que tenga un código que implemente la interfaz de los componentes no implementados y que genere respuestas simples pero útiles. De esta manera, puede comenzar a desarrollar (y diseñar) un componente a la vez y probarlo en un grado razonable.

Por supuesto, cuando se completan nuevos componentes, debe probar cómo (y si) se integran entre sí antes de continuar.

En muy poco tiempo: tome el principio de OO y de ocultación de información, ¡y suba a otro nivel!

PD: hacer muchos bocetos al diseñar, ¡es como una arquitectura real!

PPS: intente abordar el asunto desde diferentes ángulos, piense fuera de la caja (aunque la caja podría ser el camino a seguir), discutir con sus compañeros puede ser muy útil para esto ... y tiene algo de qué hablar durante el almuerzo.


En primer lugar, el diseño debe venir de tu alma. Debes sentirlo por cada una de tus fibras. Por lo general, camino por dos o tres meses antes de comenzar a hacer algo, simplemente caminar por las calles (en realidad). Y pensando. Caminar es una buena meditación, ya sabes. Así que te permite concentrarte bien.

En segundo lugar, utilice OOP y clases solo donde exista una jerarquía de objetos naturales. No lo "atornille" a eso artificialmente. Si no existe una jerarquía estricta (como en la mayoría de las aplicaciones empresariales), elija procedimientos / funcional o, al menos, utilice objetos solo como contenedores de datos con accesores aislados.

Y lo último: intenta leer esto: el algoritmo del pensamiento creativo.


Hiciste una pregunta que muchos autores utilizan para escribir un libro. Hay varias metodologías y debes elegir una que te parezca "más bonita".
Puedo recomendar el libro "Domain Driven Design" de Eric Evans. También, visite el sitio dddcommunity.org .


Honestamente, un buen paso sería regresar y observar los diagramas de flujo y la secuencia de diagramas. Hay un montón de buenos sitios que te muestran cómo hacerlo. Encuentro que es invaluable cuando veo cómo quiero dividir un programa en clases, ya que sé exactamente lo que el programa necesita que se ingrese, calcule y produzca, y cada paso se puede dividir en una parte del programa.


La fuente más interesante que conozco sobre esto es la Parte D de Object Oriented Software Construction, 2ª edición por Bertrand Meyer.

Parte D: Metodología orientada a objetos: aplicando bien el método.

19: En metodología, 20: Patrón de diseño: sistemas interactivos de múltiples paneles, 21: Caso de estudio de herencia: "deshacer" en un sistema interactivo, 22: Cómo encontrar las clases , 23: Principios del diseño de clase, 24: Uso de la herencia bien , 25: Técnicas útiles, 26: Un sentido del estilo, 27: Análisis orientado a objetos, 28: El proceso de construcción del software, 29: Enseñar el método

Curiosamente, el capítulo 22. Cómo encontrar las clases está disponible en línea.


La técnica que he usado en proyectos reales con un éxito razonable es Responsibility Driven Design, inspirada en el libro de Wirfs-Brock.

Comience con las historias de usuario de nivel superior y, junto con sus colegas, en una pizarra, dibuje las interacciones de alto nivel que implican. Esto te da la primera idea de lo que son los módulos grandes; y en una iteración o dos de juego de alto nivel CRC como la tarjeta, debería haber estabilizado una lista de los componentes principales, qué hacen y cómo interactúan.

Luego, si alguna de las responsabilidades es grande o compleja, refine esos módulos hasta que tenga cosas que sean lo suficientemente pequeñas y simples para ser objetos, realizando las interacciones dentro del módulo para cada una de las principales operaciones identificadas por las interacciones de nivel superior .

Saber cuándo parar es una cuestión de juicio (que solo viene con la experiencia).


Le recomendaría usar BlueJ y también ActiveWriter para aprender y también para desarrollar una buena comprensión de los objetos. El libro recomendado es también un buen recurso.

De Wikipedia :

BlueJ es un entorno de desarrollo integrado para el lenguaje de programación Java, desarrollado principalmente con fines educativos, pero también es adecuado para el desarrollo de software a pequeña escala.

Además, utiliza UML y para mí fue un buen recurso para comprender varias cosas sobre el modelado de objetos.

texto alt http://www.ryanknu.com/ryan/bluej.png

ActiveWriter es una herramienta para modelar entidades y relaciones, también genera código y es fácil de hacer cambios. Te ahorrará tiempo y para un desarrollo ágil es muy adecuado.

texto alternativo http://altinoren.com/activewriter/Images/Introduction_1.png


Los pasos que utilizo para el diseño inicial (llegar a un diagrama de clase) son:

  1. Recopilación de requisitos. Hable con el cliente y factorice los casos de uso para definir qué funcionalidad debe tener el software.

  2. Componer una narrativa de los casos de uso individuales.

  3. Ir a través de la narrativa y resaltar nombres (persona, lugar, cosa), como clases candidatas y verbos (acciones), como métodos / comportamientos.

  4. Descarte los nombres duplicados y elimine la funcionalidad común.

  5. Crear un diagrama de clase. Si eres un desarrollador de Java, NetBeans 6.7 de Sun tiene un módulo UML que permite la diagramación, así como la ingeniería de ida y vuelta, y es GRATIS. Eclipse (un IDE Java de código abierto), también tiene un marco de modelado, pero no tengo experiencia con él. También puede probar ArgoUML, una herramienta de código abierto.

  6. Aplique los principios de OOD para organizar sus clases (factorice la funcionalidad común, construya jerarquías, etc.)


Me temo que esta no es una respuesta que a la gente le gusta escuchar . De todos modos, déjame decirte mi opinión.

La POO debe verse como uno de los paradigmas, no como el paradigma superior. La POO es buena para resolver ciertos tipos de problemas, como desarrollar una biblioteca de GUI. También encaja en el estilo de desarrollo de software generalmente seguido por grandes compañías de software: un equipo de diseñadores o arquitectos de élite establece el diseño del software en diagramas UML o algún otro medio similar y un equipo de desarrolladores menos ilustrado traduce ese diseño en código fuente. La POO ofrece pocos beneficios si trabaja solo o con un pequeño equipo de programadores altamente talentosos. Entonces, es mejor usar un lenguaje que admita múltiples paradigmas y te ayude a crear un prototipo rápido. Python, Ruby, Lisp / Scheme, etc. son buenas opciones. El prototipo es tu diseño. Entonces mejoras en eso. Utilice el paradigma que sea mejor para resolver el problema en cuestión. Si es necesario, optimice los puntos calientes con extensiones escritas en C o en algún otro lenguaje de sistemas. Al utilizar uno de estos lenguajes, también puede obtener extensibilidad de forma gratuita, no solo a nivel de programador sino también a nivel de usuario. Los lenguajes como Lisp pueden generar y ejecutar código dinámicamente, lo que significa que los usuarios pueden extender la aplicación escribiendo pequeños fragmentos de código, en el lenguaje en el que está codificado el software. O si elige escribir el programa en C o C ++, considere incorporar un intérprete para un lenguaje pequeño como Lua. Exponer funcionalidades como complementos escritos en ese lenguaje.

Creo que, la mayoría de las veces, OOP y OOD crean software que son víctimas de un exceso de diseño.

Para resumir, mi forma preferida de escribir software es:

  1. Utiliza un lenguaje dinámico.
  2. Escribe el diseño (prototipo) en ese mismo lenguaje.
  3. Si es necesario, optimice ciertas áreas usando C / C ++.
  4. Proporcionar extensibilidad a través del intérprete del propio lenguaje de implementación.

La última característica permite que el software se adapte fácilmente a los requisitos específicos del usuario (¡incluyéndome a mí mismo)!


Si tiene experiencia en el dominio del proyecto en el que va a trabajar, por ejemplo, banca. Es fácil estructurar sus objetos y usted sabe cómo esas mejoras vienen cada dos días.

Si no tiene esa experiencia, trabaje con alguien que tenga esa experiencia y convierta esas ideas en detalles técnicos.

Si está confundido acerca de cómo estructurar el diseño de su proyecto. A ciegas siga el libro "programador pragmático". Estaba en la misma situación antes, intenta leer un capítulo de ese libro. Verá la diferencia. Cambiará su forma de pensar como desarrollador de software.


Solo citando http://www.fysh.org/~katie/computing/methodologies.txt

Y en el núcleo de RUP es un área pequeña donde tienes que usar talentos de diseño OO ... si no los tienes, es como tener una metodología para ejecutar los 100 m.

"Paso 1: escribe sobre correr muy rápido. Paso 2: Ve y dibuja un plan de la pista. Paso 3: Ve y compra pantalones cortos de lycra muy ajustados. Paso 4: corre realmente, muy, muy rápido. Paso 5: cruza la línea primero "

Es ese paso 4 que es el difícil. Pero si pones mucho énfasis en 1,2,3 y 5, es posible que nadie se dé cuenta y probablemente puedas ganar mucho dinero vendiendo la metodología a los atletas que piensan que hay un "secreto" para ser un 100m. corredor sobre


Todavía no tengo suficiente reputación para hacer comentarios (se unió hoy) o simplemente comenté la respuesta de Scott Davies. Añadiendo a lo que tenía que decir:

  1. Asegúrese de saber de qué se trata su programa antes de comenzar. Cual es tu programa ¿Qué no hará? ¿Qué problema está tratando de resolver?

  2. Su primer conjunto de casos de uso no debería ser una lista de todo lo que el programa hará eventualmente. Comience con el conjunto más pequeño de casos de uso que pueda encontrar y que aún capture la esencia de su programa. Para este sitio web, por ejemplo, los casos de uso principales pueden ser iniciar sesión , hacer una pregunta , responder una pregunta y ver preguntas y respuestas . Nada acerca de la reputación, la votación o la wiki de la comunidad, solo la esencia pura de lo que estás buscando.

  3. A medida que surjan clases potenciales, no piense en ellas solo en términos del nombre que representan, sino de las responsabilidades que tienen. Descubrí que esta es la mayor ayuda para descubrir cómo se relacionan las clases entre sí durante la ejecución del programa. Es fácil establecer relaciones como "un perro es un animal" o "un cachorro tiene una madre". Por lo general, es más difícil averiguar las relaciones que describen las interacciones en tiempo de ejecución entre objetos. Los algoritmos de los programas son al menos tan importantes como sus objetos, y son mucho más fáciles de diseñar si ha explicado cuál es el trabajo de cada clase.

  4. Una vez que tenga ese conjunto mínimo de casos de uso y objetos, comience a codificar. Obtén algo que realmente se ejecuta lo antes posible, aunque no haga mucho y probablemente se vea como una mierda. Es un punto de partida y lo obligará a responder preguntas que podría pasar por alto en un papel.

  5. Ahora regrese y elija más casos de uso, escriba cómo funcionarán, modifique su modelo de clase y escriba más código. Al igual que su primer corte, tome tan poco como pueda mientras agrega algo significativo. Enjuague y repita.

Sólo mis dos centavos. Esperemos que sea útil.


Trate de usar el desarrollo impulsado por el comportamiento. Será difícil romper tus viejos hábitos, pero he descubierto que la BDD realmente es tu mejor apuesta cuando se trata de desarrollarse en el mundo real.

http://behaviour-driven.org/


Una técnica útil es relacionar la descripción única de su problema con algo que puede encontrar en el mundo real. Por ejemplo, está modelando un complejo sistema de atención médica que tomará al mundo por sorpresa. ¿Hay ejemplos a los que pueda recurrir fácilmente para modelar esto?

En efecto. Observe cómo funcionaría la farmacia lateral o el consultorio médico.

Lleve su problema de dominio a algo comprensible para usted; algo con lo que puedes relacionarte.

Luego, una vez que los "jugadores" dentro del dominio comienzan a aparecer obvios, y usted comienza a modelar su código, opte por un enfoque de modelado "proveedor-consumidor", es decir, su código es el "proveedor" del modelo y usted es el "consumidor". ".

Relacionarse con el dominio y comprenderlo a un alto nivel es una parte clave de cualquier diseño.



Patrones de diseño

Patrones de diseño creacional

Singleton: asegúrese de que solo se cree una instancia de una clase y proporcione un punto de acceso global al objeto.

Fábrica (versión simplificada del método de fábrica): crea objetos sin exponer la lógica de creación de instancias al cliente y se refiere al objeto recién creado a través de una interfaz común.

Método de fábrica: define una interfaz para crear objetos, pero permite a las subclases decidir qué clase crear una instancia y se refiere al objeto recién creado a través de una interfaz común.

Abstract Factory: ofrece la interfaz para crear una familia de objetos relacionados, sin especificar explícitamente sus clases.

Generador: define una instancia para crear un objeto, pero permite a las subclases decidir qué clase crear una instancia y permite un control más preciso sobre el proceso de construcción.

Prototipo: especifique los tipos de objetos para crear utilizando una instancia prototípica y cree nuevos objetos copiando este prototipo.

Patrones de diseño de comportamiento

Cadena de responsabilidad - Evita adjuntar el remitente de una solicitud a su receptor, dando a otros objetos la posibilidad de manejar la solicitud también. - Los objetos se convierten en partes de una cadena y la solicitud se envía de un objeto a otro a través de la cadena hasta que uno de los objetos lo maneje.

Comando: encapsula una solicitud en un objeto, permite la parametrización de clientes con diferentes solicitudes y permite guardar las solicitudes en una cola.

Intérprete: dado un idioma, defina una representación para su gramática junto con un intérprete que use la representación para interpretar oraciones en el idioma / asigne un dominio a un idioma, el idioma a una gramática y la gramática a un diseño jerárquico orientado a objetos

Iterador: proporciona una forma de acceder a los elementos de un objeto agregado de forma secuencial sin exponer su representación subyacente.

Mediador: define un objeto que encapsula cómo interactúa un conjunto de objetos. El mediador promueve el acoplamiento suelto evitando que los objetos se refieran entre sí explícitamente, y le permite variar su interacción de forma independiente.

Observador: defina una dependencia de uno a muchos entre objetos para que cuando un objeto cambie de estado, todos sus dependientes sean notificados y actualizados automáticamente.

Estrategia: defina una familia de algoritmos, encapsule cada uno de ellos y hágalos intercambiables. La estrategia permite que el algoritmo varíe independientemente de los clientes que lo utilizan.

Método de plantilla: defina el esqueleto de un algoritmo en una operación, aplazando algunos pasos a las subclases / Método de plantilla permite a las subclases redefinir ciertos pasos de un algoritmo sin permitirles cambiar la estructura del algoritmo.

Visitante: representa una operación que se realiza en los elementos de una estructura de objeto / Visitante le permite definir una nueva operación sin cambiar las clases de los elementos sobre los que opera.

Objeto nulo: proporciona un objeto como un sustituto por la falta de un objeto de un tipo determinado. / El patrón de objetos nulos proporciona un comportamiento inteligente de no hacer nada, ocultando los detalles a sus colaboradores.

Patrones de diseño estructural

Adaptador: convierte la interfaz de una clase en otra interfaz que los clientes esperan. / Adapter permite que las clases trabajen juntas, que de otra manera no podrían debido a interfaces incompatibles.

Puente: componer objetos en estructuras de árbol para representar jerarquías de parte entera. / Compuesto permite a los clientes tratar objetos individuales y composiciones de objetos de manera uniforme.

Compuesto: componer objetos en estructuras de árbol para representar jerarquías de parte entera. / Compuesto permite a los clientes tratar objetos individuales y composiciones de objetos de manera uniforme.

Decorador: agrega responsabilidades adicionales dinámicamente a un objeto.

Peso de mosca: uso compartido para admitir una gran cantidad de objetos que tienen parte de su estado interno en común donde la otra parte del estado puede variar.

Memento: captura el estado interno de un objeto sin violar la encapsulación y, por lo tanto, proporciona un medio para restaurar el objeto al estado inicial cuando sea necesario.

Proxy: proporciona un "marcador de posición" para que un objeto controle las referencias a él.


Aprender patrones de diseño . Ha sido mi revolución personal en los últimos dos años con respecto a la POO. Conseguir un libro Yo te recomendaría este:

Head First Design Patterns

Está en Java pero puede ser extensible a cualquier idioma.