Creational Design Patterns of Design Patterns

1. The concept and role of design patterns

        Design patterns are general solutions to common problems in software design. They are experience summaries for a class of problems and are summed up from past successful experiences. Design patterns allow software developers to avoid some common mistakes while improving software design reusability, maintainability, scalability, and readability.

        Design patterns can be divided into three types: creational patterns, structural patterns, and behavioral patterns. Creational patterns include singleton pattern, factory pattern, abstract factory pattern, builder pattern and prototype pattern. Structural patterns include adapter pattern, bridge pattern, decorator pattern, facade pattern, flyweight pattern and proxy pattern. Behavioral patterns include template method pattern, command pattern, iterator pattern, observer pattern, mediator pattern, memento pattern, interpreter pattern, and state pattern.

        Different design patterns are suitable for different scenarios. For example, the Singleton pattern is suitable when you need to ensure that there is only one instance of a class, the Factory pattern is suitable for situations where you need to create a series of related objects, and the Proxy pattern is suitable for situations where you need to control access to a single object. Design patterns are not static, but vary from problem to problem. Therefore, software developers need to choose the appropriate design pattern according to the actual situation.

2. Overview and classification of creational design patterns

        Creational design patterns are patterns for the creation and instantiation of objects that aim to solve the problem of object creation in order to create objects more flexibly and separate objects from the code that uses them. Creational patterns can be divided into the following five types:

  1. Singleton Pattern: Ensures that a class has only one instance and provides a global access point to that instance.
  2. Factory Pattern: Define an interface for creating objects and let subclasses decide which class to instantiate. Factory methods defer instantiation of a class to its subclasses.
  3. Abstract Factory Pattern: Provides an interface for creating a series of related or dependent objects without specifying their concrete classes.
  4. Builder Pattern: Separate the construction of a complex object from its representation so that the same construction process can create different representations.
  5. Prototype Pattern: Use prototype instances to specify the types of objects to be created, and create new objects by copying these prototypes.

        These design patterns are widely used in practical applications and can improve code reusability, maintainability and scalability. At the same time, they also have different applicable scenarios and advantages and disadvantages, which require developers to evaluate and choose in practical applications.

3. Simple factory pattern: factory method pattern and abstract factory pattern

        Simple factory pattern, factory method pattern and abstract factory pattern are all creational design patterns, and their purpose is to separate the creation of objects from the use code, and improve the scalability and maintainability of the code.

        Simple Factory Pattern: Also known as the static factory method pattern, it creates objects through a factory class without instantiating objects directly through the new keyword. This factory class determines the type of object to be created based on the parameters passed in. The simple factory pattern has only one factory class, so the extensibility is not as good as the other two patterns. But it is simple to implement and more convenient to use.

// 创建产品接口
interface Product {
    void show();
}

// 创建具体产品类
class ConcreteProduct1 implements Product {
    @Override
    public void show() {
        System.out.println("具体产品1");
    }
}

class ConcreteProduct2 implements Product {
    @Override
    public void show() {
        System.out.println("具体产品2");
    }
}

// 创建工厂类
class SimpleFactory {
    public static Product createProduct(int type) {
        switch (type) {
            case 1:
                return new ConcreteProduct1();
            case 2:
                return new ConcreteProduct2();
            default:
                return null;
        }
    }
}

// 测试类
public class SimpleFactoryDemo {
    public static void main(String[] args) {
        Product product1 = SimpleFactory.createProduct(1);
        product1.show();

        Product product2 = SimpleFactory.createProduct(2);
        product2.show();
    }
}

        Factory Method Pattern: Also known as the polymorphic factory pattern, it defines an interface for creating objects, but lets subclasses decide which class to instantiate. This factory method defers the instantiation of a class to its subclasses. The advantage of this is that when you need to add a new product, you only need to add a specific product class and a corresponding factory class without modifying the existing code, which conforms to the principle of openness and closure.

        

// 创建产品接口
interface Product {
    void show();
}

// 创建具体产品类
class ConcreteProduct1 implements Product {
    @Override
    public void show() {
        System.out.println("具体产品1");
    }
}

class ConcreteProduct2 implements Product {
    @Override
    public void show() {
        System.out.println("具体产品2");
    }
}

// 创建工厂接口
interface Factory {
    Product createProduct();
}

// 创建具体工厂类
class ConcreteFactory1 implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProduct1();
    }
}

class ConcreteFactory2 implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProduct2();
    }
}

// 测试类
public class FactoryMethodDemo {
    public static void main(String[] args) {
        Factory factory1 = new ConcreteFactory1();
        Product product1 = factory1.createProduct();
        product1.show();

        Factory factory2 = new ConcreteFactory2();
        Product product2 = factory2.createProduct();
        product2.show();
    }
}

        Abstract Factory Pattern: Also known as Toolbox Pattern, it provides an interface for creating a series of related or dependent objects without specifying their specific classes. The abstract factory pattern creates a set of related product classes together without specifying a specific class. The abstract factory pattern can create products of a product family together, so the consistency of a group of products can be guaranteed. But it is not as extensible as the factory method pattern.

        

// 创建产品接口
interface Product1 {
    void show();
}

interface Product2 {
    void show();
}

// 创建具体产品类
class ConcreteProduct1 implements Product1 {
    @Override
    public void show() {
        System.out.println("具体产品1");
    }
}

class ConcreteProduct2 implements Product2 {
    @Override
    public void show() {
        System.out.println("具体产品2");
    }
}

// 创建工厂接口
interface Factory {
    Product1 createProduct1();
    Product2 createProduct2();
}

// 创建具体工厂类
class ConcreteFactory1 implements Factory {
    @Override
    public Product1 createProduct1() {
        return new ConcreteProduct1();
    }

    @Override
    public Product2 createProduct2() {
        return new ConcreteProduct2();
    }
}

class ConcreteFactory2 implements Factory {
    @Override
    public Product1 createProduct1() {
        return new ConcreteProduct1();
    }

    @Override

These factory patterns are widely used in practical applications. The simple factory pattern is suitable for simple object creation scenarios, the factory method pattern is suitable for scenarios with more complex product levels, and the abstract factory pattern is suitable for the creation of product families. Developers need to choose and apply according to the actual situation.

4. Builder mode

        The builder pattern is a creational design pattern that can split the creation process of complex objects into multiple simple steps, making the code clearer, easier to maintain and expand. Unlike simple factories, factory methods, and abstract factories, the builder pattern focuses on the complex construction process of creating objects, rather than focusing only on the creation of objects.

Builder mode can be divided into the following roles:

  1. Product class (Product): defines the objects that need to be built.

  2. Abstract builder class (Builder): defines an abstract interface for building products, including multiple abstract methods for building products.

  3. Concrete Builder Class (ConcreteBuilder): implement the abstract builder interface to complete the construction process of specific products.

  4. Director: Call the builder interface to build products in a specific order.

// 创建产品类
class Product {
    private String partA;
    private String partB;
    private String partC;

    public String getPartA() {
        return partA;
    }

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public String getPartB() {
        return partB;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public String getPartC() {
        return partC;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    @Override
    public String toString() {
        return "Product{" +
                "partA='" + partA + '\'' +
                ", partB='" + partB + '\'' +
                ", partC='" + partC + '\'' +
                '}';
    }
}

// 创建抽象建造者类
abstract class Builder {
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    public abstract Product getResult();
}

// 创建具体建造者类
class ConcreteBuilder extends Builder {
    private Product product = new Product();

    @Override
    public void buildPartA() {
        product.setPartA("PartA");
    }

    @Override
    public void buildPartB() {
        product.setPartB("PartB");
    }

    @Override
    public void buildPartC() {
        product.setPartC("PartC");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

// 创建指挥者类
class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

// 测试类
public class BuilderDemo {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();
        Product product = builder.getResult();
        System.out.println(product);
    }
}

        In this example, we create a product class (Product), which contains multiple components, and we use the builder pattern to create this complex object. First, we define an abstract builder class (Builder), which contains multiple abstract methods for defining the specific construction process. Then, we define a concrete builder class (ConcreteBuilder), which implements the abstract builder interface and completes the concrete construction process. Finally, we create a Director class that uses the builder interface to create concrete products and calls the methods in the builder interface in a specific order. In the test class, we create a concrete builder object, and then use the director object to call the methods in the builder interface, thus creating a complex object with multiple components.

        The builder pattern is widely used in practical projects, especially when creating complex objects. For example, in Java, the StringBuilder class uses the builder pattern to create string objects. In the Spring framework, there are also many examples of applying the builder pattern. For example, the XmlBeanDefinitionReader class uses the builder pattern to create BeanDefinition objects.

        In short, the builder pattern can help us split the creation process of complex objects into multiple simple steps, making the code clearer, easier to maintain and expand. It can avoid using a large number of constructors or setter methods in the code, thereby improving the readability and maintainability of the code.

5. Prototype pattern

        Prototype pattern (Prototype Pattern) is a creational design pattern, which can create new objects by copying existing objects without re-instantiation. The prototype mode is usually suitable for creating complex objects or when the creation process is time-consuming. Creating new objects by copying existing objects can improve creation efficiency and avoid the problem of repeatedly creating similar objects.

// 定义一个原型接口
public interface Prototype {
    Prototype clone();
}

// 定义一个具体的原型类
public class ConcretePrototype implements Prototype {
    private String name;

    public ConcretePrototype(String name) {
        this.name = name;
    }

    public Prototype clone() {
        return new ConcretePrototype(name);
    }

    public String getName() {
        return name;
    }
}

// 定义一个客户端类
public class Client {
    public static void main(String[] args) {
        Prototype prototype = new ConcretePrototype("原型对象");
        Prototype clone = prototype.clone();
        System.out.println("原型对象的名称:" + prototype.getName());
        System.out.println("克隆对象的名称:" + clone.getName());
    }
}

        In the above demo, we first defined a prototype interface (Prototype), which contains a clone method (clone), used to copy the current object and create a new object. Then, we define a specific prototype class (ConcretePrototype), which implements the prototype interface and completes the specific cloning process. Finally, we created a client class (Client), which creates a new object by calling the clone method of the prototype object, and outputs the name of the prototype object and the cloned object.

        The prototype mode is also widely used in actual projects. For example, in Java, the Object class is the root class of all classes. It provides a clone method to create new objects by copying existing objects. In the Spring framework, there are also many examples of applying the prototype pattern. For example, when creating a Bean, Spring will first create a prototype object, and then create multiple similar Bean objects by copying the prototype object.

        In short, the prototype mode can help us quickly create complex objects, thereby improving the efficiency and maintainability of the code. At the same time, it also avoids the problem of repeatedly creating similar objects in the code, thereby reducing memory overhead.

6. Singleton mode

        Singleton Pattern (Singleton Pattern) is a creational design pattern that ensures that a class has only one instance and provides a global access point to access this unique instance.

        There are many ways to implement the singleton mode. Below we introduce two of the more commonly used ways.

       Hungry Chinese singleton pattern

        Hungry-style singleton mode is the simplest implementation, it creates a singleton object when the class is loaded, so it is also called static singleton mode. The following is a sample code for a simple hungry Chinese singleton pattern:

public class Singleton {
    // 私有化构造函数,确保外部无法实例化该类
    private Singleton() {
    }

    // 定义静态的单例对象
    private static Singleton instance = new Singleton();

    // 提供公共的访问方法,用于获取单例对象
    public static Singleton getInstance() {
        return instance;
    }
}

        In the above sample code, we define a Singleton class, which contains a private constructor to ensure that the class cannot be instantiated externally. Then, we define a static singleton object instance, and create this object when the class is loaded. Finally, we provide a public access method getInstance for obtaining singleton objects.

        Lazy singleton pattern

public class Singleton {
    // 私有化构造函数,确保外部无法实例化该类
    private Singleton() {
    }

    // 定义静态的单例对象
    private static Singleton instance;

    // 提供公共的访问方法,用于获取单例对象
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

        The lazy singleton pattern is a lazy loading implementation that creates a singleton object when the getInstance method is called for the first time. Here is a sample code for a simple lazy singleton pattern:

public class Singleton {
    // 私有化构造函数,确保外部无法实例化该类
    private Singleton() {
    }

    // 定义静态的单例对象
    private static Singleton instance;

    // 提供公共的访问方法,用于获取单例对象
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

        In the sample code above, we also defined a Singleton class and privatized the constructor. The difference is that we do not create a singleton object when the class is loaded, but judge in the getInstance method. If the instance is null, a new singleton object is created, otherwise the existing singleton object is returned directly.

        The singleton pattern is also a very widely used design pattern in actual projects. For example, in Java, the Runtime class is a singleton class, which provides a public access point to obtain a unique instance. In the Spring framework, there are also many examples of applying the singleton pattern. For example, BeanFactory is a singleton class that is responsible for managing all Bean objects.

        In short, the singleton pattern can help us ensure that there is only one instance of a class, avoiding the problem of repeatedly creating the same object in the code, thereby reducing memory overhead and improving the reliability of the code.

Guess you like

Origin blog.csdn.net/zz18532164242/article/details/130352458