Hello everyone, I am Wolf King, a programmer who loves playing ball

This is the second part of design patterns, we all know that there are three kinds of “factory patterns”, “simple factory, factory method, abstract factory”. In this article, let’s recognize “factory patterns” **


1, an overview of the

The factory method pattern is a creative design pattern that provides a method to create an object in a parent class, allowing subclasses to determine the type of object to instantiate.

2. Applicable scenarios

1) The category, number or dependency of objects are not determined. 2) Need to extend the tool library or internal components. 3) Objects that need to be reused (such as resource pools).

3, the instance,

There are the following business scenarios: a store, selling a variety of goods, including car, ship, plane.

3.1 Do not use factory mode

Define three entity classes

import lombok.Data;

/** * Car */
@Data
public class Car {

    private String name;

    private String price;

    public void run() {
        System.out.println("the car is running"); }}Copy the code
import lombok.Data;

/** * Plane */
@Data
public class Plane {

    private String name;

    private String price;

    public void run() {
        System.out.println("the Plane is running"); }}Copy the code
import lombok.Data;

/** * Ship */
@Data
public class Ship {

    private String name;

    private String price;

    public void run() {
        System.out.println("the Ship is running"); }}Copy the code

Define interfaces and implementations

As shown in the figure above: an interface IShop has an implementation class ShopImpl, and the methods to get three products are defined three times in this interface.

/** * IShop */
public interface IShop {

    /** * get the car */
    Car getCar();

    /** * get the ship */
    Ship getShip();

    /** * obtain aircraft */
    Plane getPlane();
}
Copy the code
import com.cloud.bssp.designpatterns.factorymethod.withoutdesign.Car;
import com.cloud.bssp.designpatterns.factorymethod.withoutdesign.IShop;
import com.cloud.bssp.designpatterns.factorymethod.withoutdesign.Plane;
import com.cloud.bssp.designpatterns.factorymethod.withoutdesign.Ship;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/** * ShopImpl */
@Slf4j
@Service
public class ShopImpl implements IShop {
    @Override
    public Car getCar() {
        log.info("this is car");
        return new Car();
    }

    @Override
    public Ship getShip() {
        log.info("this is Ship");
        return new Ship();
    }

    @Override
    public Plane getPlane() {
        log.info("this is Plane");
        return newPlane(); }}Copy the code

Create a test class


/** * test */@RunWith(SpringRunner.class) @SpringBootTest(classes = BsspUserApplication.class) public class TestDemo { @Autowired private IShop shop; @Test public void testWithout() { Car car = shop.getCar(); car.run(); Ship ship = shop.getShip(); ship.run(); Plane plane = shop.getPlane(); plane.run(); }}Copy the code

The execution result

2021- 01- 10 14:54:24.078  INFO 16884 --- [           main] c.c.b.d.f.withoutdesign.impl.ShopImpl    : this is car
the car is running
2021- 01- 10 14:54:24.078  INFO 16884 --- [           main] c.c.b.d.f.withoutdesign.impl.ShopImpl    : this is Ship
the Ship is running
2021- 01- 10 14:54:24.078  INFO 16884 --- [           main] c.c.b.d.f.withoutdesign.impl.ShopImpl    : this is Plane
the Plane is running
Copy the code

3.2 Using factory mode

Create a Product interface and define the run() method

/** * Product */
public interface Product {

    /** * run */
    void run();
}
Copy the code

Define three entity classes

import lombok.Data;

/** * Car */
@Data
public class Car implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the car is running"); }}Copy the code
import lombok.Data;

/** * Plane */
@Data
public class Plane implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the Plane is running"); }}Copy the code
import lombok.Data;

/** * Ship */
@Data
public class Ship implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the Ship is running"); }}Copy the code

The interface and implementation are shown below

One interface returns Product, and three implementations each return three Product entities.

Define a factory method interface

/** * IShop */
public interface IShop {

    /** * get goods */
    Product getProduct();
}
Copy the code

Define the factory interface implementation

/** * Ship */
@Data
public class Ship implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the Ship is running"); }}Copy the code
/** * Plane */
@Data
public class Plane implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the Plane is running"); }}Copy the code
import lombok.Data;

/** * Car */
@Data
public class Car implements Product{

    private String name;

    private String price;

    @Override
    public void run() {
        System.out.println("the car is running"); }}Copy the code

Define a test class


/** * test */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BsspUserApplication.class)
public class TestDemo {

    @Autowired
    private IShop shipImpl;

    @Autowired
    private IShop carImpl;

    @Autowired
    private IShop planeImpl;

    @Test
    public void testUsed() {
        // The following uses injection, noting that each implementation of the factory IShop specifies the bean name
        Product car = carImpl.getProduct();

        Product ship = shipImpl.getProduct();

        Product plane = planeImpl.getProduct();

        // Use new in the following way
// IShop planeImpl = new PlaneImpl();
// Product plane = planeImpl.getProduct();
//
//
// IShop carImpl = new CarImpl();
// Product car = carImpl.getProduct();
// car.run();
//
// IShop shipImpl = new ShipImpl();
// Product ship = shipImpl.getProduct();car.run(); plane.run(); ship.run(); }}Copy the code

The results

2021- 01- 10 15:01:59.394  INFO 21132 --- [           main] c.c.b.d.f.usedesign.impl.CarImpl         : this is car
2021- 01- 10 15:01:59.394  INFO 21132 --- [           main] c.c.b.d.f.usedesign.impl.ShipImpl        : this is Ship
2021- 01- 10 15:01:59.394  INFO 21132 --- [           main] c.c.b.d.f.usedesign.impl.PlaneImpl       : this is plane
the car is running
the Plane is running
the Ship is running
Copy the code

4, analysis,

Analyze and compare the above two implementations:

Entity class

“Using factory-issued entity classes” defines an interface that can define some common methods. Entity classes can implement the interface to override the methods with the same name.

“In an entity class that does not use a factory”, although methods can be customized, there is no restriction on method names. With the increasing number of subsequent entities, there may be a variety of common method names, resulting in code confusion, which is not conducive to unification.

interface

Using the factory approach, which provides a unified interface, internally provides a unified way to get a product, which product it returns is specified by its implementation method. This interface is never modified, only extended in its implementation class.

** Unused factory methods ** also provides an interface, but internally provides three methods to get three products, which will increase as more products become available.

The implementation class

** “using the factory method” ** implements the implementation classes of each product separately for different products, and each implementation class returns the corresponding product without any coupling between each other.

** “factory method not used” ** there are three methods of obtaining products in one implementation class. As the product category increases, this class will become longer and longer, which is easy to cause code coupling and too long, which is not conducive to code reading and management, and poor scalability. Every new implementation class needs to be modified.

5, summary

Finally, summarize the pros and cons of using the factory approach in the above example:

Advantages:

“1) In accordance with the open and closed principle, open for expansion, closed for modification.”

“2) In accordance with the Demeter principle, there is no correlation between classes, reducing coupling.”

“3) Conform to a single responsibility, where a class or method is responsible for only one thing.”

Disadvantages:

“A lot of subclasses were introduced and the code got complicated.”

Java Technology public account: Garnett’s Way of Java. The public number has a large number of technical articles, massive video resources, beautiful brain map, might as well pay attention to it! Get lots of learning resources and free books!

Forwarding moments is the biggest support for me!

\

Click “like and watching” if you feel something! Thank you for your support!