Six common design modes: II. Factory mode

Posted by twooton on Sat, 22 Jan 2022 03:33:40 +0100

2.1 introduction

The core essence of the factory model:

  • The instantiated object is not created with new, but replaced with factory method;
  • The implementation class will be selected and the object will be created for unified management and control, so as to decouple the caller from the implementation class.

The core idea is to realize the separation of creator and caller.

Detailed classification:

  • Simple factory mode (used to produce any product in the same hierarchical structure. If a new product is added, the existing code needs to be overwritten. There is only one factory in this mode, also known as static factory mode)
  • Factory method mode (used to produce fixed products in the same hierarchical structure. Any product can be added. In this mode, there are multiple factories and the same interface is implemented. When adding a product, the original code is not changed, but a new class is created)
  • Abstract factory pattern (create other factories around a super factory. The super factory is also called the factory of other factories)

This type of design pattern is a creation pattern.

2.2. Simple factory mode

Take consumers buying a car as an example, use the simple factory mode to realize the output "buy Wuling car" on the console And "buy a BMW!".

First create the interface: Car, which contains the method name():

public interface Car {
    void name();
}

Create implementation class Wuling implementation interface Car:

public class Wuling implements Car {
    @Override
    public void name() {
        System.out.println("Buy Wuling car!");
    }
}

Create an implementation class Baoma to implement the interface Car:

public class Baoma implements Car {
    @Override
    public void name() {
        System.out.println("Buy a BMW!");
    }
}

Here's the point. Create the car factory class CarFactory, and the car factory instantiates the object:

public class CarFactory {
    public static Car getCar(String car) {
        if (car.equals("Wuling")){
            return new Wuling();
        } else if (car.equals("bmw")){
            return new Baoma();
        } else {
            return null;
        }
    }
}

A Consumer who buys a car directly calls the factory class to buy a car according to the car name:

public class Consumer {
    public static void main(String[] args) {
        Car car1 = CarFactory.getCar("Wuling");
        Car car2 = CarFactory.getCar("bmw");

        car1.name();
        car2.name();
    }
}

The console results are shown in the figure below:

In addition, if you want to buy other cars, you need to create the implementation class of the car and modify the code of the car factory, but doing so will violate the opening and closing principle. In terms of design principles, simple factory mode is not supported, but it is most used in actual development.

2.3 factory method mode

The factory method mode does not violate the opening and closing principle.

Based on the simple factory mode, it creates the car factory interface, and then creates the car factory interface one by one to realize the car factory interface:

There are already interface Car, implementation class Wuling and implementation class Baoma. The code is the same as the simple factory mode. Now create the interface Car engineering CarFactory:

public interface CarFactory {
    Car getCar();
}

Create the implementation class WulingFactory to realize the interface between the vehicle and the factory, and produce Wuling vehicle:

public class WulingFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Wuling();
    }
}

Create an implementation class BaomaFactory to implement the car factory interface and produce BMW cars:

public class BaomaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Baoma();
    }
}

After the factory is set up, the following is the code Consumer for the Consumer to buy the car, which directly calls the method to the factory of the car:

public class Consumer {
    public static void main(String[] args) {
        Car car1 = new WulingFactory().getCar();
        Car car2 = new BaomaFactory().getCar();
        car1.name();
        car2.name();
    }
}

The result is the same as the simple factory model.

If consumers want to buy other cars, they need to create the implementation class of the Car to implement the interface Car and the Car factory class of the Car to implement CarFactory. The factory method mode meets the opening and closing principle, but it has more code than the simple factory mode.

2.4 abstract factory mode

Definition: the abstract factory pattern provides a way to create a series of related or interdependent interfaces without specifying their specific classes.

Applicable scenarios:

  • The client (i.e. application layer) does not depend on the details of how product class instances are created and implemented.
  • Emphasize that a series of related product objects (belonging to the same product family) are used together, and creating objects requires a lot of repetitive code.
  • Provide a library of product classes. All products appear with the same interface, so that the client does not depend on the specific implementation.

advantage:

  • The code isolation of specific products in the application layer does not need to care about the details of creation;
  • Create a series of products together.

Disadvantages:

  • All product sets that may be created are specified, and it is difficult to expand new products in the product family;
  • It increases the abstraction and understanding difficulty of the system.

For example: use the abstract factory mode to output Xiaomi series products "call with Xiaomi mobile phone", "send text message with Xiaomi mobile phone" and "turn on WIFI in Xiaomi router" on the console.

First, we need two interfaces, one for the production of mobile phone IphoneProduct:

public interface IphoneProduct {
    void CallUp();// Phone call
    void SendSMS();// Send SMS via mobile phone
}

A production router RouterProduct:

public interface RouterProduct {
    void OpenWIFI();// Turn on WIFI in router
}

After the interface is written, the following Xiaomi product implements the two interfaces, creates an implementation class XiaomiIphone, and implements the interface IphoneProduct:

public class XiaomiIphone implements IphoneProduct {
    @Override
    public void CallUp() {
        System.out.println("Millet phone call");
    }

    @Override
    public void SendSMS() {
        System.out.println("Xiaomi texting");
    }
}

Create an implementation class XiaomiRouter to implement the interface RouterProduct:

public class XiaomiRouter implements RouterProduct {
    @Override
    public void OpenWIFI() {
        System.out.println("Millet router on WIFI");
    }
}

Let's focus on creating the abstract product factory interface ProductFactory:

public interface ProductFactory {
    // Production of mobile phones
    IphoneProduct iphoneProduct();
    // Production router
    RouterProduct routerProduct();
}

Then create XiaomiFactory, a factory for Xiaomi series products, and implement the ProductFactory interface:

public class XiaomiFactory implements ProductFactory{
    // Production of Xiaomi mobile phone
    @Override
    public IphoneProduct iphoneProduct() {
        return new XiaomiIphone();
    }
    // Production of Xiaomi router
    @Override
    public RouterProduct routerProduct() {
        return new XiaomiRouter();
    }
}

Finally, create Consumer consumers, purchase Xiaomi mobile phones, send text messages, purchase Xiaomi routers, and open WIFI:

public class Consumer {
    public static void main(String[] args) {
        System.out.println("====== Xiaomi series products ======");
        // Create Xiaomi factory
        XiaomiFactory xiaomiFactory = new XiaomiFactory();
        // Xiaomi factory produces mobile phones
        IphoneProduct iphoneProduct = xiaomiFactory.iphoneProduct();
        iphoneProduct.CallUp();
        iphoneProduct.SendSMS();
        // Xiaomi factory produces routers
        RouterProduct routerProduct = xiaomiFactory.routerProduct();
        routerProduct.OpenWIFI();
    }
}

The console operation results are as follows:

If you want to produce mobile phones and routers of other series of products, you need to create three implementation classes of this series, one implementing IphoneProduct interface, one implementing RouterProduct interface and one implementing ProductFactory interface.

Topics: Java Back-end