[design mode] simple factory mode

Posted by foyer on Mon, 14 Feb 2022 02:03:05 +0100

Wechat search: Menon StayUp
Home address: https://gozhuyinglong.github.io
Source code sharing: https://github.com/gozhuyinglong/blog-demos

Simple Factory Pattern is a simple implementation of factory pattern. It belongs to creation pattern. There is only one "factory" class in the Simple Factory Pattern, which can create different "product" instances according to the type.

In other words, the creation of "product" instances is no longer through direct new, but through the "factory". The client does not need to care about the details of instance creation.

In the simple factory pattern, the method of creating "product" instances is usually static, so the simple factory pattern is also called Static Factory Method Pattern.

Simple factory mode is not among the 23 design modes of GOF. Some data say that it is not a design mode, but more like a programming habit. However, due to its simple logic and frequent use, it is still necessary to have an in-depth understanding.

role

It can be seen from the above introduction that the simple factory mode mainly has the following roles:

  • Abstract Product: it is the common interface of all concrete products. The create Product instance method in the factory class should return this interface (interface oriented programming).
  • Concrete product: an object created in a factory class.
  • Factory: it is the core class of the simple factory pattern and is responsible for the creation logic of all product instances. It has a method to create a product instance by type, which is usually static.
  • Client: the factory above serves the client. The client calls the method in the factory class to obtain the product instance.

The following is the UML class diagram of the pattern:

realization

The following is a mobile phone case to explain the implementation of this mode.

Abstract product interface: Phone

Create a mobile interface that can make calls and send text messages.

/**
 * Mobile interface
 */
public interface Phone {

    /**
     * phone
     */
    void call();

    /**
     * send message
     */
    void sendSMS();
}

Two specific product categories: XiaomiPhone and RedmiPhone

Create two implementation classes for the mobile interface, one is Xiaomi mobile phone and the other is Hongmi mobile phone. Of course, there can be more implementation classes.

/**
 * Xiaomi mobile phone implementation class
 */
public class XiaomiPhone implements Phone {
    @Override
    public void call() {
        System.out.println("Call with Xiaomi mobile phone");
    }

    @Override
    public void sendSMS() {
        System.out.println("Use Xiaomi mobile phone to send text messages");
    }
}

/**
 * Hongmi mobile phone implementation class
 */
public class RedmiPhone implements Phone {
    @Override
    public void call() {
        System.out.println("Call with Hongmi mobile phone");
    }

    @Override
    public void sendSMS() {
        System.out.println("Use Hongmi mobile phone to send text messages");
    }
}

Factory class: PhoneFactory

Create a mobile phone factory class, which can obtain mobile phone instances according to mobile phone types.

Note: in general, this type should be represented by an enumeration class

/**
 * Mobile phone factory
 */
public class PhoneFactory {

    /**
     * Get phone by type
     *
     * @param type
     * @return
     */
    public static Phone createPhone(String type) {
        switch (type) {
            case "xiaomi":
                return new XiaomiPhone();
            case "redmi":
                return new RedmiPhone();
            default:
                return null;
        }
    }
}

Client class: client

Create a client class to call the mobile phone factory class to generate a mobile phone instance.

/**
 * Client class
 */
public class Client {

  public static void main(String[] args) {
        System.out.println("================Mi phones================");
        Phone xiaomiPhone = PhoneFactory.createPhone("xiaomi");
        if (xiaomiPhone != null) {
            xiaomiPhone.call();
            xiaomiPhone.sendSMS();
        }

        System.out.println("================Red rice mobile phone================");
        Phone redmiPhone = PhoneFactory.createPhone("redmi");
        if (redmiPhone != null) {
            redmiPhone.call();
            redmiPhone.sendSMS();
        }

    }
}

Operation results

Run the client main method, and the following contents will be printed:

================Mi phones================
Call with Xiaomi mobile phone
 Use Xiaomi mobile phone to send text messages
================Red rice mobile phone================
Call with Hongmi mobile phone
 Use Hongmi mobile phone to send text messages

Advantages and disadvantages

advantage:

  • Separate the creation and use of objects. The creation of objects is entrusted to a special factory class. The client does not need to care about how to create them, but only how to use them.
  • There is only one factory class, with clear logic and easy to understand.

Disadvantages:

  • The factory class is not flexible enough. Every time a product is added, the factory class must be modified, and the code coupling is too high.
  • The factory class is responsible for the creation of all products, which violates a single responsibility

Typical application

java.util.Calendar class is a calendar abstract class that comes with Java. It is a typical simple factory mode.

The role of this class is not only a factory, but also an abstract product. It has three sub categories: BuddhistCalendar, Japanese Imperial calendar and Gregorian calendar. These three sub categories are specific product roles.

The Calendar class has multiple overloaded methods getInstance() to get instances, but they will eventually call the createCalendar() method to generate specific instances. It can also be seen from the following code snippet that it creates corresponding instances according to different region types.

// Gets the calendar instance of the default time zone and region
public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

// Gets the calendar instance for the specified time zone and default area
public static Calendar getInstance(TimeZone zone)
{
    return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
}

// Gets the default time zone and region of the specified calendar
public static Calendar getInstance(Locale aLocale)
{
    return createCalendar(TimeZone.getDefault(), aLocale);
}

// Gets the calendar instance of the specified time zone and the specified region
public static Calendar getInstance(TimeZone zone, Locale aLocale)
{
    return createCalendar(zone, aLocale);
}

// How to get the calendar instance
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
    // ......
    Calendar cal = null;

    if (aLocale.hasExtensions()) {
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
            switch (caltype) {
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }
    if (cal == null) {
        if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
            cal = new BuddhistCalendar(zone, aLocale);
        } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                   && aLocale.getCountry() == "JP") {
            cal = new JapaneseImperialCalendar(zone, aLocale);
        } else {
            cal = new GregorianCalendar(zone, aLocale);
        }
    }
    return cal;
}

Complete code

Please visit my Github for the complete code. If it is helpful to you, please give me a reply ⭐, Thank you~~ 🌹🌹🌹

https://github.com/gozhuyinglong/blog-demos/blob/main/design-patterns/src/main/java/io/github/gozhuyinglong/designpatterns/factory/FactorySimple.java

Recommended reading

Topics: Java Design Pattern