Implementación del patrón abstracto de la fábrica con diferentes proveedores para el producto -- java campo con design-patterns campo con abstract-factory camp codereview Relacionados El problema

Implementation of Abstract Factory pattern with different vendors for product


2
vote

problema

Español

Estoy estudiando sobre los principios de diseño y los patrones de diseño. He implementado un patrón de fábrica abstracto según mi comprensión. El escenario que he considerado es el siguiente:

  1. Hay una organización 'DruckStandards.LTD' para establecer estándares Reglas para el dibujo.
  2. Hay otras dos organizaciones 'shape.ltd' y 'EnhancedShape.LTD' que proporciona formas según las reglas establecidas por El 'Drutsandsardards.ltd'.
  3. Hay otra organización 'graphics.ltd' que usa las formas implementadas por shape.ltd y 'enhancedshape.ltd'.

Código de DUDUMSTESTARD.LTD

  1. dibujable.java

      package com.drawing.drawable;  /**  * Interface for DrawableFactory, implement this for any new Drawable shape.  *  * @author krishna.k@drawingstandards.com  *  */ public interface Drawable {     /**      * draws the concrete drawable.      */     public void draw(); }   
  2. dibujablefactory.java

      package com.drawing.drawable.factory;  import com.drawing.drawable.Drawable;  /**  * Abstract Factory to create the concrete drawables based on the input. Extend  * this class to provide concrete implementation for creation of any new product  *  * @author krishna.k@drawingstandards.com  *  */ public abstract class DrawableFactory {     /**      *      * @param factory      * @return concrete drawable object as created by the factory      */     public final Drawable getDrawable(DrawableFactory factory) {         return factory.createDrawable();     }     /**      *      * @return Drawable created by the concrete factory.      */     protected abstract Drawable createDrawable(); }   

Se han lanzado estas clases a través de JAR.

ahora código de formas.ltd

  1. círculo.java

      package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable class representing a Circle.  *  * @author krishna.k@shape.com  *  */ public class Circle implements Drawable {     private int radius;      /**      * Takes radius of the circle as input      *      * @param radius      */     public Circle(int radius) {         this.radius = radius;     }      /**      * provides concrte implementation for draw method specific to circle. It      * uses the length of the radius passed in the constructor to draw the      * circle.      */     @Override     public void draw() {         System.out.println("Drawing the circle with radius = " + radius);     }  }   
  2. square.java

      package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable for drawing a square.  *  * @author krishna.k@shape.com  *  */ public class Square implements Drawable {     private int sideLength;      /**      * Takes the input as length of the side      *      * @param sideLength      */     public Square(int sideLength) {         this.sideLength = sideLength;     }      /**      * provides concrete implementation to the draw method, specific to square,      * defined in Drawable. interface. It uses the length of the side passed in      * the constructor to draw the square.      */     @Override     public void draw() {         System.out.println("Drawing a Square with side length =" + sideLength);     }  }   
  3. triangle.java

      package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable representing a Triangle  *  * @author krishna.k@shape.com  *  */ public class Triangle implements Drawable {     private int sideOneLength;     private int sideTwoLength;     private int sideThreeLength;      /**      * takes input for the three sides.      *      * @param sideOneLength      * @param sideTwoLength      * @param sideThreeLength      */     public Triangle(int sideOneLength, int sideTwoLength, int sideThreeLength) {         this.sideOneLength = sideOneLength;         this.sideTwoLength = sideTwoLength;         this.sideThreeLength = sideThreeLength;     }      /**      * provides concrete implementation to draw method specific to the circle.      *      * It uses the length of the three sides passed in the constructor to draw      * the triangle.      */     @Override     public void draw() {         System.out.println("Drawing a Triangle with side one length = " + sideOneLength + " side two length = "                 + sideTwoLength + " side three length = " + sideThreeLength);     } }   

ahora las clases de fábrica

  1. CircuFactory.Java

      answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 0  
  2. squeseFactory.Java

      answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 1  
  3. trianglefactory.java

      answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 2  

El código de enenancedshapes.ltd

Clases similares según las formas.LTD (Circle.Java, triangle.java, square.java y la fábrica correspondiente Clases.) Bajo el paquete answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 3 y answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 4

ahora el código de 'graphics.ltd' utilizando las formas implementadas por dos proveedores anteriores.

  1. shapepainter.java

      answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 5  
  2. driverprogram.java

      answer("abcabcabcabc"):output = 4 answer("abccbaabccba"): output = 2 answer("abcabcd"): output = 1 6  

Por favor, proporcione sus valiosas comentarios de revisión.

Original en ingles

I am studying about design principles and design patterns. I have implemented an Abstract factory pattern as per my understanding. The scenario I have considered is as follows :

  1. There is an organization 'DrawingStandards.ltd' for setting standard rules for drawing.
  2. There are two Other organizations 'Shape.ltd' and 'EnhancedShape.ltd' which provides Shapes as per the rules set by the 'DrawingStandards.ltd'.
  3. There is another organization 'Graphics.ltd' which uses the Shapes implemented by Shape.ltd and 'EnhancedShape.ltd'.

Code from DrawingStandard.ltd

  1. Drawable.java

    package com.drawing.drawable;  /**  * Interface for DrawableFactory, implement this for any new Drawable shape.  *  * @author krishna.k@drawingstandards.com  *  */ public interface Drawable {     /**      * draws the concrete drawable.      */     public void draw(); } 
  2. DrawableFactory.java

    package com.drawing.drawable.factory;  import com.drawing.drawable.Drawable;  /**  * Abstract Factory to create the concrete drawables based on the input. Extend  * this class to provide concrete implementation for creation of any new product  *  * @author krishna.k@drawingstandards.com  *  */ public abstract class DrawableFactory {     /**      *      * @param factory      * @return concrete drawable object as created by the factory      */     public final Drawable getDrawable(DrawableFactory factory) {         return factory.createDrawable();     }     /**      *      * @return Drawable created by the concrete factory.      */     protected abstract Drawable createDrawable(); } 

These classes have been released via jar.

Now Code from Shapes.ltd

  1. Circle.java

    package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable class representing a Circle.  *  * @author krishna.k@shape.com  *  */ public class Circle implements Drawable {     private int radius;      /**      * Takes radius of the circle as input      *      * @param radius      */     public Circle(int radius) {         this.radius = radius;     }      /**      * provides concrte implementation for draw method specific to circle. It      * uses the length of the radius passed in the constructor to draw the      * circle.      */     @Override     public void draw() {         System.out.println("Drawing the circle with radius = " + radius);     }  } 
  2. Square.java

    package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable for drawing a square.  *  * @author krishna.k@shape.com  *  */ public class Square implements Drawable {     private int sideLength;      /**      * Takes the input as length of the side      *      * @param sideLength      */     public Square(int sideLength) {         this.sideLength = sideLength;     }      /**      * provides concrete implementation to the draw method, specific to square,      * defined in Drawable. interface. It uses the length of the side passed in      * the constructor to draw the square.      */     @Override     public void draw() {         System.out.println("Drawing a Square with side length =" + sideLength);     }  } 
  3. Triangle.java

    package com.shape.drawables;  import com.drawing.drawable.Drawable;  /**  * Drawable representing a Triangle  *  * @author krishna.k@shape.com  *  */ public class Triangle implements Drawable {     private int sideOneLength;     private int sideTwoLength;     private int sideThreeLength;      /**      * takes input for the three sides.      *      * @param sideOneLength      * @param sideTwoLength      * @param sideThreeLength      */     public Triangle(int sideOneLength, int sideTwoLength, int sideThreeLength) {         this.sideOneLength = sideOneLength;         this.sideTwoLength = sideTwoLength;         this.sideThreeLength = sideThreeLength;     }      /**      * provides concrete implementation to draw method specific to the circle.      *      * It uses the length of the three sides passed in the constructor to draw      * the triangle.      */     @Override     public void draw() {         System.out.println("Drawing a Triangle with side one length = " + sideOneLength + " side two length = "                 + sideTwoLength + " side three length = " + sideThreeLength);     } } 

Now the factory classes

  1. CircleFactory.java

    package com.shape.drawables.factories;  import com.drawing.drawable.Drawable; import com.drawing.drawable.factory.DrawableFactory; import com.shape.drawables.Circle;  /**  * Concrete Factory for Cicle provided by Shape.ltd  *  * @author krishna.k@shape.com  *  */ public class CircleFactory extends DrawableFactory {     private int radius;      /**      * takes length radius as parameter      *      * @param radius      */     public CircleFactory(int radius) {         this.radius = radius;     }      @Override     protected Drawable createDrawable() {         return new Circle(radius);     }  } 
  2. SquareFactory.java

    package com.shape.drawables.factories;  import com.drawing.drawable.Drawable; import com.drawing.drawable.factory.DrawableFactory; import com.shape.drawables.Square;  /**  * Concrete factory for Square.by Shape.ltd  *  * @author krishna.k@shape.com  *  */ public class SquareFactory extends DrawableFactory {     private int sideLength;      /**      * takes the length of the side of the square      *      * @param sideLength      */     public SquareFactory(int sideLength) {         this.sideLength = sideLength;     }      @Override     protected Drawable createDrawable() {         return new Square(sideLength);     }  } 
  3. TriangleFactory.java

    package com.shape.drawables.factories;  import com.drawing.drawable.Drawable; import com.drawing.drawable.factory.DrawableFactory; import com.shape.drawables.Triangle;  /**  * Concrete implementation of Factory class for Triangle  *  * @author krishna.k@shape.com  *  */ public class TriangleFactory extends DrawableFactory {     private int sideOneLength;     private int sideTwoLength;     private int sideThreeLength;      /**      * Takes the length of three sides as parameter      *      * @param sideOneLength      * @param sideTwoLength      * @param sideThreeLength      */     public TriangleFactory(int sideOneLength, int sideTwoLength, int sideThreeLength) {         this.sideOneLength = sideOneLength;         this.sideTwoLength = sideTwoLength;         this.sideThreeLength = sideThreeLength;     }      @Override     protected Drawable createDrawable() {         return new Triangle(sideOneLength, sideTwoLength, sideThreeLength);     } } 

The code from EnhancedShapes.ltd

Similar classes as provided by Shapes.ltd (Circle.java,Triangle.Java,Square.java and the corresponding factory classes.) under the package package com.enhancedshape.drawables and package com.enhancedshape.drawables.factories;

Now the code from 'Graphics.ltd' Using the shapes implemented by two vendors above.

  1. ShapePainter.java

    package com.graphichs;  import com.drawing.drawable.Drawable; import com.drawing.drawable.factory.DrawableFactory;  /**  * Fetches the best factory as per the resources availability and provides the  * shape  *  * @author krishna.k@graphics.com  *  */ public class ShapePainter {     private static long MIN_MEMORY_FOR_ENHANCED_SHAPE = 20796757;      /**      * Returns the best Square as per the resources available      *      * @param sideLength      * @return Square      */     public Drawable getSquare(int sideLength) {         DrawableFactory factory = null;         if (Runtime.getRuntime().freeMemory() < MIN_MEMORY_FOR_ENHANCED_SHAPE) {             factory = new com.shape.drawables.factories.SquareFactory(sideLength);         } else {             factory = new com.enhancedshape.drawables.factories.SquareFactory(sideLength);         }         return DrawableFactory.getDrawable(factory);     }      /**      * Returns the best Circle as per the resources available      *      * @param radius      * @return Circle      */     public Drawable getCircle(int radius) {         DrawableFactory factory = null;         if (Runtime.getRuntime().freeMemory() < MIN_MEMORY_FOR_ENHANCED_SHAPE) {             factory = new com.shape.drawables.factories.CircleFactory(radius);         } else {             factory = new com.enhancedshape.drawables.factories.CircleFactory(radius);         }         return DrawableFactory.getDrawable(factory);     }      /**      * Returns the best Triangle as per the resources available      *      * @param sideOneLength      * @param sideTwoLength      * @param sideThreeLength      * @return Triangle      */     public Drawable getTriangle(int sideOneLength, int sideTwoLength, int sideThreeLength) {         DrawableFactory factory = null;         if (Runtime.getRuntime().freeMemory() < MIN_MEMORY_FOR_ENHANCED_SHAPE) {             factory = new com.shape.drawables.factories.TriangleFactory(sideOneLength, sideTwoLength, sideThreeLength);         } else {             factory = new com.enhancedshape.drawables.factories.TriangleFactory(sideOneLength, sideTwoLength,                     sideThreeLength);         }         return DrawableFactory.getDrawable(factory);     } } 
  2. DriverProgram.java

    package com.graphichs;  import com.drawing.drawable.Drawable;  public class DriverProgram {     public static void main(String[] args) {         ShapePainter shapePainter = new ShapePainter();         Drawable circle = shapePainter.getCircle(20);         Drawable square = shapePainter.getSquare(30);         circle.draw();         square.draw();     } } 

Please provide your valuable review feedback.

        

Lista de respuestas

6
 
vote

Si es su objetivo aprender sobre el patrón abstracto de la fábrica, eso está bien. En ese caso, haría dos cambios en DrawableFactory :

  • Deshágase del método getDrawable (¿Estaba destinado a ser estático?). No proporciona ningún valor. También haga createDrawable() Public.

  • Crear un parámetro de tipo para el tipo de Drawable creado. Luego, puede escribir un código de tipo seguro que llama a un 99887766555544334 , hace algo con el Drawable y lo devuelve como su tipo de concreto.

  • HACER DrawableFactory Una interfaz. En Java 8, las interfaces con un método se denominan interfaces funcionales y se pueden construir con lambdas y referencias de métodos. Incluso si esta funcionalidad está avanzada para usted, otros que usan 9988776655544337 pueden querer aprovecharla.

  • Haz los campos de la final de sus implementaciones de fábrica. Luego, sus fábricas son inmutables y, por lo tanto, subprocesan seguras y tienen menos probabilidades de tener errores en la carretera.

entonces su código se vería como:

  public interface class DrawableFactory<D extends Drawable> {     D createDrawable(); }  public class CircleFactory implements DrawableFactory<Circle> {     private final int radius;     public Circle createDrawable() {         return new Circle(radius);     } }   

etc.

Pero si su objetivo es también aprender cuando para usar este patrón, creo que este caso es un buen ejemplo de sobrecarga. ¿Qué valor hace CircleFactory , getDrawable0 , y 99887766555443311 Proporcionar? Parece que simplemente envuelven el getDrawable2 , getDrawable3 y getDrawable4 constructores. No crearía fábricas para ese propósito, crearía directamente el 998877766555443315 . Si los requisitos cambiaron de una manera que justificara fábricas, lo haría luego y solo entonces Refactor para introducir fábricas.

Un punto más: getDrawable6 es una forma muy mala de determinar si hay suficiente memoria para crear un objeto. Le dice cuánta memoria es gratuita en este momento, pero no tiene en cuenta la cantidad de memoria que se llena con basura que podría ser liberada si se necesitaba el espacio y tampoco tiene cuenta de cuánto podría crecer el tamaño del montón si usa todo la memoria. La única forma confiable de la que soy consciente de determinar si hay suficiente memoria para crear un objeto es tratar de crearlo. Luego, se capturaría getDrawable7 y devolverá el objeto más pequeño en ese caso.


Pedimos más comentarios sobre el patrón de fábrica abstracto. Te daré mis dos centavos aquí.

¿Cuál es el propósito del patrón de fábrica? Resuma el proceso de creación de un objeto. Oculta la implementación exacta y puede usar información sobre el sistema o sobre los parámetros pasados ​​para elegir la implementación. Puede tener múltiples líneas de código ocultas detrás de un solo método, llame a conveniencia.

Las fábricas abstractas proporcionan un nivel adicional de abstracción, ya que ahora la implementación de la fábrica tampoco está establecida en piedra. El patrón de fábrica abstracto proporciona una API uniforme en múltiples implementaciones de fábricas y permite el código que instancie la fábrica para elegir la implementación y luego aprovechar la fábrica para eliminar el código que sea agnóstico a la implementación. (Por ejemplo, este código puede usar la fábrica para crear 10 instancias y ponerlos en una lista.)

El patrón abstracto de fábrica proporciona así dos niveles de abstracción : uno sobre la implementación de fábrica y la otra sobre la implementación de los elementos que crea la fábrica. La abstracción es una de las herramientas más poderosas en OOP. Sin embargo, si se usa en exceso, puede hacer que la rotonda de su código y sea difícil de entender. Utilice solo el patrón abstracto de la fábrica cuando realmente necesita ambos niveles de abstracción.

 

If it is your goal to learn about the abstract factory pattern, that is fine. In that case I would make two changes to DrawableFactory:

  • Get rid of the getDrawable method (was it meant to be static?). It doesn't provide any value. Also make createDrawable() public.

  • Create a type parameter for the type of Drawable created. You could then write type-safe code that calls an arbitrary DrawableFactory, does something with the Drawable, and returns it as its concrete type.

  • Make DrawableFactory an interface. In Java 8, interfaces with one method are called functional interfaces and can be constructed with lambdas and method references. Even if this functionality is advanced for you, others who use DrawableFactory might want to take advantage of it.

  • Make the fields of your factory implementations final. Then your factories are immutable and thus thread safe and less likely to have bugs down the road.

Then your code would look like:

public interface class DrawableFactory<D extends Drawable> {     D createDrawable(); }  public class CircleFactory implements DrawableFactory<Circle> {     private final int radius;     public Circle createDrawable() {         return new Circle(radius);     } } 

etc.

But if your goal is to also learn when to use this pattern, I think this case is a good example of over-design. What value do CircleFactory, TriangleFactory, and SquareFactory provide? They seem to simply wrap the Circle, Triangle, and Square constructors. I would not create factories for that purpose - I would create the Drawables directly. If requirements did change in a way that warranted factories, I would then and only then refactor to introduce factories.

One more point: Runtime.getRuntime().freeMemory() is a very bad way to determine if there is enough memory to create an object. It tells you how much memory is free at the moment but doesn't account for how much memory is filled with garbage that could be freed if the space were needed and nor does it account for how much the heap size could grow if you use all the memory. The only reliable way I am aware of to determine if there is enough memory to create an object is to try to create it. Then you would catch OutOfMemoryError and return the smaller object in that case.


You asked for more feedback on the abstract factory pattern. I'll give you my two cents here.

What is the purpose of the factory pattern? It abstracts out the process of creating an object. It hides the exact implementation and can use information about the system or about parameters passed in to choose the implementation. It can have multiple lines of code hidden behind a single method call for convenience.

Abstract factories provide an additional level of abstraction, as now the implementation of the factory is also not set in stone. The abstract factory pattern provides a uniform API across multiple factory implementations and allows the code that instantiates the factory to choose the implementation and then pass the factory off to separate code that is agnostic to the implementation. (For example, this code might use the factory to create 10 instances and put them in a list.)

The abstract factory pattern thus provides two levels of abstraction: one over the factory implementation and the other over the implementation of the items that the factory creates. Abstraction is one of the most powerful tools in OOP. However, if used excessively, it can make your code roundabout and difficult to understand. Only use the abstract factory pattern when you actually need both levels of abstraction.

 
 
     
     
2
 
vote

Creo que ha perdido una gran oportunidad para usar la fábrica;)

Mira tu código:

  getDrawable8  

I Mi opinión que es el lugar para la fábrica: Envolviendo la decisión de qué paquete - getDrawable9 createDrawable()020 Para usar.

escribiría algo como esto:

  createDrawable()1  

y ponga todas las cosas de la comprobación de la memoria en el createDrawable()2 clase.

El siguiente paso será, como sugirió el secreto de Solomonoff, deshacerse de su createDrawable()3 . Luego, createDrawable()4 estará listo para ser renombrado ... Por ejemplo, createDrawable()5 ;)

 

I think that you have missed a really great opportunity to use factory ;)

Look at your code:

    DrawableFactory factory = null;     if (Runtime.getRuntime().freeMemory() < MIN_MEMORY_FOR_ENHANCED_SHAPE) {         factory = new com.shape.drawables.factories.CircleFactory(radius);     } else {         factory = new com.enhancedshape.drawables.factories.CircleFactory(radius);     }     return DrawableFactory.getDrawable(factory); 

I my opinion that is the place for factory: wrapping the decision of which package - shape or enchancedshape to use.

I'd write something like this:

    DrawableFactory factory = new FactoryOfFactories(Runtime.getRuntime().freeMemory());     return DrawableFactory.getDrawable(factory); 

And put all memory checking stuff in the FactoryOfFactories class.

The next step will be, as Solomonoff's Secret suggested, getting rid of your DrawableFactory. Then, FactoryOfFactories will be ready to be renamed... for example to DrawableFactory ;)

 
 

Relacionados problema

0  Objetos burlones usando fábrica abstracta  ( Mocking objects using abstract factory ) 
Por alguna vez, estoy tratando de hacer una biblioteca burlona para C # que se burla de los objetos con solo 1 línea de código. Estoy usando un patrón abstrac...

3  Patrón abstracto de fábrica implementado en Java  ( Abstract factory pattern implemented in java ) 
Necesito una revisión de código en mi patrón abstracto de fábrica escrito en Java. Encuentre los dos enumeres animaltype.java y diettype.java a continuación...

3  Patrón abstracto de fábrica en Python  ( Abstract factory pattern in python ) 
He estado leyendo hoy sobre el patrón de fábrica abstracto y traté de hacer la siguiente implementación. He visto muchas implementaciones en Internet, donde...

1  Módulo de fábrica para convertir estructuras de datos DOM / ORM  ( Factory module to convert dom orm data structures ) 
El siguiente código es parte de una API de procesamiento de datos de bienes raíces. Se está invocando por varios módulos de un software que traduce datos in...

-3  Alguna forma de crear un patrón de fábrica para la aplicación de resorte [cerrado]  ( Some way to create factory pattern for spring application ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

2  Reloj PDCurses usando diseño abstracto de fábrica  ( Pdcurses clock using abstract factory design ) 
Actualmente estoy aprendiendo a usar PDCurses y decidí hacer un reloj con él. ** Nota: este reloj que usa El patrón de diseño abstracto de fábrica no es lo ...

3  Implementación de la fábrica DAO  ( Implementing dao factory ) 
Estoy tratando de hacer tres diferentes tipos de DAOS con 4 subtipos de cada uno. Tengo RAM, SQL y serial con cada uno tiene cuatro subtipos. ¿Es necesario ...

0  Diseño abstracto de fábrica Java  ( Abstract factory design java ) 
Soy nuevo para diseñar la implementación del patrón y me gustaría solidificar firmemente mi conocimiento para ser tan bueno un programador que pueda. ¿Es esta...

3  Fábrica abstracta usando genéricos  ( Abstract factory using generics ) 
Estoy aprendiendo patrones de diseño y he implementado la fábrica abstracta usando los genéricos C # .NET. ¿Es esta implementación correcta o no? ¿O hay algun...

0  DAO del cliente simulado usando patrón abstracto de fábrica en reaccionar  ( Mock customer dao using abstract factory pattern in react ) 
Quería implementar el método abstracto de la fábrica en TypeScript con reaccionar por SharePoint Framework WEBPART. Así que traté de traducir ideas de este...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos