Twenty three design patterns - Abstract Factory Pattern

introduce

Intent: provide an interface to create a series of related or interdependent objects without specifying their specific classes.

Main solution: mainly solve the problem of interface selection.

When to use: the system has more than one product family, and the system only consumes one family of products.

How to solve: in a product family, define multiple products.

Key code: aggregate multiple similar products in one factory.

Application example: for work, in order to attend some parties, there must be two or more sets of clothes, such as business clothes (complete sets, a series of specific products), fashion clothes (complete sets, a series of specific products), and even for a family, there may be business women's clothes, business men's clothes, fashion women's clothes, fashion men's clothes, which are also complete sets, that is, a series of specific products. Product. Suppose a situation (in reality, it doesn't exist, otherwise, it's impossible to enter communism, but it's helpful to explain the abstract factory mode), in your home, a certain wardrobe (specific factory) can only store a certain kind of such clothes (complete set, a series of specific products), and each time you take this complete set of clothes, you will naturally take it out of this closet. With the idea of OOP, all the wardrobes (concrete factories) are one of the wardrobes (Abstract factories), and each complete set of clothes includes specific tops (a specific product), pants (a specific product). These specific tops are actually tops (Abstract products), and specific pants are pants (another Abstract product).

Advantage: when multiple objects in a product family are designed to work together, it can ensure that clients always use only the objects in the same product family.

Disadvantages: product family extension is very difficult. To add a series of a product, you need to add code in both abstract creators and concrete ones.

Usage scenario: 1. QQ skin replacement, a whole set of skin replacement. 2. Generate programs of different operating systems.

Note: product family is difficult to expand, and product grade is easy to expand.

Realization

We will create the Shape and Color interfaces and entity classes that implement them. The next step is to create the abstract factory class AbstractFactory. Then define the factory classes ShapeFactory and ColorFactory, both of which extend AbstractFactory. Then create a factory creator / generator class, FactoryProducer.

AbstractFactoryPatternDemo, our demo class uses FactoryProducer to get AbstractFactory objects. It will pass Shape information (CIRCLE / RECTANGLE / SQUARE) to AbstractFactory to get the type of object it needs. It also passes Color information (RED / GREEN / BLUE) to AbstractFactory to get the type of object it needs.

Step 1

Create an interface for the shape.

Create the entity class that implements the interface.

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

Step 2

Create an interface for colors.

Create the entity class that implements the interface.

public interface Color {
   void fill();
}

public class Red implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}

public class Green implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}

public class Blue implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}

Step 3

Create abstract classes for Color and Shape objects to get the factory.

public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape) ;
}

Step 4

Create the factory class that extends AbstractFactory, and generate the object of entity class based on the given information.

public class ShapeFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      return null;
   }
}
public class ColorFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      } else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      } else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}

Step 5

Create a factory creator / generator class to get the factory by passing shape or color information.

public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}

Step 6

Use FactoryProducer to get AbstractFactory, and pass type information to get object of entity class.

public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
 
      //Get shape factory
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
 
      //Get objects with the shape of Circle
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //Call the draw method of Circle
      shape1.draw();
 
      //Get object with Rectangle shape
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //Call the draw method of Rectangle
      shape2.draw();
      
      //Get objects with Square shape
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //Call Square's draw method
      shape3.draw();
 
      //Get color factory
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //Get objects with Red color
      Color color1 = colorFactory.getColor("RED");
 
      //Call Red's fill method
      color1.fill();
 
      //Get object with color Green
      Color color2 = colorFactory.getColor("Green");
 
      //Call Green's fill method
      color2.fill();
 
      //Get objects with Blue color
      Color color3 = colorFactory.getColor("BLUE");
 
      //Call Blue's fill method
      color3.fill();
   }
}

Step 7

Execute the program and output the result:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.

 

Posted by philvia on Sun, 27 Oct 2019 00:38:21 -0700