From tableware production to abstract factory

In the last article, we explored and understood what is Factory mode Next, let's move on to the abstract factory

What is an abstract factory

Abstract factory pattern is a creative design pattern, which can create a series of related objects without specifying their specific classes

understand

My understanding of the abstract factory pattern is the factory pattern that exists to create a set of products. For example:

  1. Web page style can use abstract factory mode, one click skin change, punk painting style, Q version painting style, minimalist painting style, etc. Although the painting styles are different, each painting style will have page details such as button color, button border size and so on.
  2. The map style in the game can also use abstract factory mode, lava map, ice and snow map, desert map, etc. Although the map styles are different, each map will detail parameters such as earth, trees, moving force and so on.
  3. Tableware manufacturers can also use the abstract factory model to produce disposable tableware and recyclable tableware. Although the factories are different, they all produce bowls, chopsticks, plates and other tableware.

Tableware factory

Let's use the tableware factory as an example to understand what an abstract factory is

  1. First, let's define the factory and the products to be produced

    /**
     * Top interface of tableware
     * @author wangxing
     */
    public interface Tableware {
    
        /**
         * use
         */
        void use();
    
        /**
         * recovery
         */
        void recycle();
    }
    
    /**
     * bowl
     * @author wangxing
     */
    public interface Bowl extends Tableware {}
    
    /**
     * chopsticks
     * @author wangxing
     */
    public interface Chopsticks extends Tableware {}
    
    /**
     * plate
     * @author wangxing
     */
    public interface Plate extends Tableware {}
    
    /**
     * Tableware factory
     * @author wangxing
     */
    public interface TablewareFactory {
    
        /**
         * Production of chopsticks
         * @param user User of chopsticks
         * @return chopsticks
         */
        Chopsticks createChopsticks(String user);
    
        /**
         * Production bowl
         * @param user Bowl user
         * @return
         */
        Bowl createBowl(String user);
    
        /**
         * Production plate
         * @param user Plate user
         * @return
         */
        Plate createPlate(String user);
    }
    

    We defined Bowl bowl, Plate and Chopsticks in the interface, and the factory needs to be able to produce Bowl createBowl, Plate and Chopsticks. However, there is no specific statement on how to produce and the specific product type.

  2. Next, we define a factory for disposable tableware and some disposable tableware

    /**
     * Disposable bowl
     * @author wangxing
     */
    public class DisposableBowl implements Bowl{
        @Override
        public void use() {
            System.out.println("This is a disposable bowl");
        }
    
        @Override
        public void recycle() {
            System.out.println("Just throw it away");
        }
    }
    /**
     * one-off chopsticks
     * @author wangxing
     */
    public class DisposableChopsticks implements Chopsticks{
        @Override
        public void use() {
            System.out.println("This is disposable chopsticks");
        }
    
        @Override
        public void recycle() {
            System.out.println("Throw it away");
        }
    }
    /**
     * Disposable plate
     * @author wangxing
     */
    public class DisposablePlate implements Plate {
        @Override
        public void use() {
            System.out.println("This is a disposable plate");
        }
    
        @Override
        public void recycle() {
            System.out.println("Throw it away");
        }
    }
    
    /**
     * Disposable tableware factory
     * @author wangxing
     */
    public class DisposableTablewareFactory implements TablewareFactory {
        @Override
        public Chopsticks createChopsticks(String user) {
            return new DisposableChopsticks();
        }
    
        @Override
        public Bowl createBowl(String user) {
            return new DisposableBowl();
        }
    
        @Override
        public Plate createPlate(String user) {
            return new DisposablePlate();
        }
    }
    

    Through this disposable tableware factory, we can produce a lot of disposable tableware.

  3. Then we define a tableware factory for recyclable tableware

    /**
     * Reusable bowl
     * @author wangxing
     */
    public class RepeatableBowl implements Bowl {
        @Override
        public void use() {
            System.out.println("This bowl can be reused");
        }
    
        @Override
        public void recycle() {
            System.out.println("Wash it after use");
        }
    }
    
    /**
     * Reusable chopsticks
     * @author wangxing
     */
    public class RepeatableChopsticks implements Chopsticks {
        @Override
        public void use() {
            System.out.println("This is a reusable chopstick");
        }
    
        @Override
        public void recycle() {
            System.out.println("Wash it after use");
        }
    }
    
    /**
     * Reusable plate
     * @author wangxing
     */
    public class RepeatablePlate implements Plate {
        @Override
        public void use() {
            System.out.println("This is a disposable plate");
        }
    
        @Override
        public void recycle() {
            System.out.println("Throw it away");
        }
    }
    
    /**
     * Factory for reusable tableware
     * @author wangxing
     */
    public class RepeatableTablewareFactory implements TablewareFactory {
        private final ConcurrentHashMap<String, Chopsticks> chopsticksCache = new ConcurrentHashMap<>();
        private final ConcurrentHashMap<String, Bowl> bowlCache = new ConcurrentHashMap<>();
        private final ConcurrentHashMap<String, Plate> plateCache = new ConcurrentHashMap<>();
    
        @Override
        public Chopsticks createChopsticks(String user) {
            return chopsticksCache.computeIfAbsent(user, k -> new RepeatableChopsticks());
        }
    
        @Override
        public Bowl createBowl(String user) {
            return bowlCache.computeIfAbsent(user, k -> new RepeatableBowl());
        }
    
        @Override
        public Plate createPlate(String user) {
            return plateCache.computeIfAbsent(user, k -> new RepeatablePlate());
        }
    }
    

summary

Through the above code, we define two product families. One is disposable tableware and the other is recyclable tableware. When we use disposable tableware, we use DisposableTablewareFactory as the concrete implementation of TablewareFactory. When we use recyclable tableware, we use repeatable TablewareFactory as the concrete implementation of TablewareFactory. We just changed the implementation class of the factory to achieve the effect of replacing two different tableware.

Comparison with factory method

  1. It seems that the abstract factory just produces more products than the factory method. If a factory produces only one product, this is the factory method, but if you want to generate multiple products (the concept of product family is introduced here), it is the abstract factory.
  2. The factory approach emphasizes products, while the abstract factory emphasizes product families.
  3. Use the factory method when your product is flexible or the creation of the product needs to be hidden. When you have a range of products (styles) that are flexible, use abstract factories.
  4. Finally, again, products - > factory methods, product families - > Abstract factories

Tags: Java Design Pattern

Posted on Fri, 26 Nov 2021 21:36:24 -0500 by Brad7928