Learning software design patterns (taking Java as an example)


Software Design Pattern, also known as design pattern, is a set of code design experience that is repeatedly used, known by most people, classified and catalogued

It describes some recurring problems in the software design process and the solutions to the problems. In other words, it is a series of routines to solve specific problems and a summary of the code design experience of predecessors. It is universal and can be used repeatedly.

Its purpose is to improve the reusability, readability and reliability of the code.

Single case model

Singleton pattern is a frequently used pattern in design patterns. It is widely used in various open source frameworks and application systems. Solve the problem that a class has only one object in memory.

definition:

Singleton mode is also called singleton mode or singleton mode. That is to ensure that a class has only one instance and provide a global access point to access it. The "Singleton" in singleton pattern is usually used to represent those system components (or resources) that are essentially unique. Such as file system, resource manager, etc.

analysis:

  • A class can only create one instance. From this, we can know that this class cannot be created externally, but only inside the class. So how to achieve this! We can set the constructor of this class as a private variable.

  • Now that we have made the constructor private, how do we create the class internally? And ensure its uniqueness? We can declare a static private member variable and a public static function to judge whether it is unique and has been created.

main points:

  • A class can only have one instance.
  • Must be created automatically.
  • You must provide this instance yourself as a whole system.

In a multithreaded environment, if multiple threads call GetInstance() method at the same time, and they all measure instance==null, multiple objects will be generated in the system, which violates the original intention of the singleton mode. Therefore, we provide two methods: lazy mode and hungry mode

Lazy mode

package com.boke.danli;

public class Main {
    public static void main(String args[]){
        EagerSingleton a,b;
        a=EagerSingleton.GetInstance();
        b=EagerSingleton.GetInstance();
        if(a==b){
            System.out.println("Instance unique");
        }
    }

}

public class EagerSingleton {
    private static final EagerSingleton instance=new EagerSingleton();
    private EagerSingleton(){

    }
    public static EagerSingleton GetInstance(){
        return instance;
    }

}

Hungry man model

public class LazySingleton {
    private static LazySingleton instance=null;
    private LazySingleton(){

    }
    public static LazySingleton getInstance(){
        if(instance==null){
            synchronized (LazySingleton.class){
                if(instance==null){
                    instance=new LazySingleton();
                }
            }
        }
    return instance;
    }
}

Advantages and disadvantages of singleton mode

advantage
  • Instance unique
  • save resources
  • Variable instances are allowed. Based on the singleton mode, we can expand it and use a method similar to the singleton control to obtain a specified number of object instances, which not only saves system resources, but also solves the problem that too many singleton objects are shared, which is detrimental to performance.
shortcoming
  • No abstraction layer
  • The accusation of singleton class is too heavy.
  • At present, many object-oriented languages (such as Java and C#) provide automatic garbage collection technology. Therefore, if the instantiated shared object is not used for a long time, the system will consider it garbage, automatically destroy and recycle resources, and re instantiate it the next time, which will lead to the loss of the state of the shared singleton object.

Factory mode

definition

Factory mode is the most commonly used instantiation object mode. It is a mode that uses factory method instead of new operation. The famous Jive forum makes extensive use of factory mode, which can be seen everywhere in Java program system. Because factory mode is equivalent to creating new instance objects, we often need to generate instance objects according to Class. For example, a = new a() factory mode is also used to create instance objects. Therefore, we need to pay more attention to new in the future. Can we consider using factory mode? Although doing so, we may do more work, But it will bring greater scalability and less modification to your system.

To put it simply, the factory mode is to provide a manufacturer that generates instantiated objects. Each factory will provide similar objects (implement common interfaces). When we need instantiated objects of a class, we don't need to care how the server obtains the objects. We can directly put forward our requirements to the corresponding factory (it realizes the separation of client and server).

classification

  • Simple factory mode
  • Factory method model
  • Abstract method pattern

Factory method model

Composition of plant method mode:

  • Factory class role: This is the core of this pattern and contains certain business logic and judgment logic. In java, it is often implemented by a specific class.
  • Abstract product role: it is generally the parent class or implemented interface inherited by a specific product. It is implemented by an interface or abstract class in java.
  • Specific product role: the object created by the factory class is an instance of this role. It is implemented by a specific class in java.

Abstract factory pattern

Abstract factory pattern definition: it provides an interface for access classes to create a group of related or interdependent objects, and the access class can obtain the pattern structure of products of different levels of the same family without specifying the specific class of the product. Here are two concepts: same family and same level.

Using the abstract factory pattern requires the following conditions:

  • There are multiple product families in the system. Each specific factory creates products of the same family but belonging to different hierarchical structures.
  • The system can only consume one family of products at a time, that is, the products of the same family can be used together.

As an upgraded version of the factory method pattern, the composition of the abstract factory pattern is the same as that of the factory method pattern. It is also composed of four elements: abstract factory, concrete factory, abstract product and concrete product. However, the number of methods in the abstract factory is different, and the number of abstract products is also different.

  • Abstract Factory: it provides an interface for creating products. It contains multiple methods for creating products newProduct(), which can create multiple products of different levels.
  • Concrete Factory: it mainly implements multiple abstract methods in the abstract factory to complete the creation of specific products.
  • Abstract Product: it defines the Product specification and describes the main features and functions of the Product. The abstract factory pattern has multiple Abstract products.
  • Concrete product: it implements the interface defined by the abstract product role and is created by the concrete factory. It has a many-to-one relationship with the concrete factory.
code implementation

There are two farms. The first farm is used to raise cattle and vegetables, and the second farm is used to raise horses and fruits. After analysis, our products are of different types, and the factory method mode can only complete the production of the same series of products. If we need to produce different series of products, we need to use the abstract factory mode.

/**
 * @author  hz
 * @version 1.0
 */
public class FarmTest {
    public static void main(String[] args) {
        try {
            Farm f;
            Animal a;
            Plant p;
            //Read the corresponding configuration information for the production plant
            f = (Farm) ReadXML.getObject();
            a = f.newAnimal();
            p = f.newPlant();
            a.show();
            p.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
//Abstract products: Animals
interface Animal {
    public void show();
}
//Specific products: Horses
class Horse implements Animal {
    public Horse() {
        System.out.println("Generation of specific horses");
    }
    public void show() {
        System.out.println("Perform corresponding operations for horses");
    }
}
//Specific products: Cattle
class Cattle implements Animal {

    public Cattle() {
        //Generation of specific cattle
        System.out.println("Generation of specific cattle");
    }
    public void show() {
        System.out.println("Perform corresponding operations for horses");
    }
}
//Abstract products: Plants
interface Plant {
    public void show();
}
//Specific products: Fruits
class Fruitage implements Plant {

    public Fruitage() {
        System.out.println("Specific fruit generation");
    }
    public void show() {
        System.out.println("Perform corresponding operations for fruits");
    }
}
//Specific products: Vegetables
class Vegetables implements Plant {
    public Vegetables() {
        System.out.println("Specific vegetable generation");
    }
    public void show() {
        System.out.println("Perform the corresponding operations of vegetables");
    }
}
//Abstract factory: Farm class
interface Farm {
    public Animal newAnimal();
    public Plant newPlant();
}
//Specific factory: Farm 1
class SGfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("A new cow is born!");
        return new Cattle();
    }
    public Plant newPlant() {
        System.out.println("Vegetables grow!");
        return new Vegetables();
    }
}
//Specific factory: Farm 2
class SRfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("The new horse was born!");
        return new Horse();
    }
    public Plant newPlant() {
        System.out.println("Fruit grows!");
        return new Fruitage();
    }
}
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.File;

/**
 * @author hz
 * @version 1.0
 */
public class ReadXML2 {
    public static Object getObject() {
        try {
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/AbstractFactory/config.xml"));
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode = nl.item(0).getFirstChild();
            String cName = "AbstractFactory." + classNode.getNodeValue();
            System.out.println("New class name:" + cName);
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

advantage

Simple factory mode:
The factory class contains necessary judgment logic to decide when to create an instance of which product class. The client can exempt the responsibility of directly creating product objects and only "consume" products. The simple factory model realizes the division of responsibility through this approach. The simple factory pattern can decide which specific class object should be created according to the given information. Through it, the outside world can get rid of the embarrassing situation of directly creating specific product objects. The outside world is isolated from specific classes, and the coupling is low. Clearly distinguish their respective responsibilities and powers, which is conducive to the optimization of the whole software architecture.

Factory method mode:
Factory method pattern is designed to overcome the shortcomings of simple factory pattern (mainly to meet OCP). With the increase of product classes, factory classes in simple factory mode need to add many methods (or codes), while each specific factory class in factory method mode only completes a single task, and the code is simple. The factory method pattern fully satisfies OCP, that is, it has very good scalability.

Abstract factory pattern:
The abstract factory model is mainly to deal with the demand change of "new series". Separating the specific classes, the abstract factory pattern helps you control the classes of objects created by an application, because a factory encapsulates the responsibility and process of creating product objects. It separates the implementation of customers and classes. Customers manipulate instances through their abstract interfaces. The class names of products are also separated in the implementation of specific factories. They do not appear in customer code. It makes it easy to exchange product lines. A concrete factory class appears only once in an application -- that is, when it is initialized. This makes it easy to change the specific factory of an application. It only needs to change the specific factory to use different product configurations. This is because an abstract factory creates a complete product family, so the whole product family will change immediately. It is conducive to product consistency. When a series of product objects are designed to work together, it is important that an application can only use the objects in the same series at a time, which is easy to implement by the abstract factory. The abstract factory pattern is helpful to the division of labor of such a team, reduces the coupling between modules and improves the development efficiency of the team.

shortcoming

Simple factory mode:
When the product has a complex multi-layer hierarchical structure, the factory class has only itself, which is the disadvantage of the model. Because the factory class centralizes all product creation logic, once products are added or deleted, the whole system will be affected. It is difficult to expand the system. Once a new product is added, the factory logic has to be modified, which may cause the factory logic to be too complex and violate the "open closed" principle (OCP). In addition, the simple factory mode usually uses the static factory method, which makes it impossible to inherit from subclasses, resulting in the failure of factory roles to form an inheritance based hierarchical structure.

Factory method mode:
If a specific product class needs to be modified, the corresponding factory class may need to be modified. When multiple product classes need to be modified at the same time, the modification of factory classes will become quite troublesome. For example, every time a product is added, a sub factory will be added accordingly, which will increase the amount of additional development.

Abstract factory pattern:
The abstract factory pattern is difficult to cope with the demand changes of "new objects". It is difficult to support new types of products. It is difficult to expand Abstract factories to produce new kinds of products. This is because the abstract factory almost determines the product set that can be created. To support new types of products, you need to extend the factory interface, which will involve the change of the abstract factory class and all its subclasses.

Article citation

Tags: Java

Posted on Mon, 20 Sep 2021 23:24:07 -0400 by safetguy