Design patterns should be learned this way

Posted by gunslinger008 on Sat, 30 Oct 2021 13:23:26 +0200

1. Factory mode

1. Concept

Factory Pattern is one of the most commonly used design patterns in Java. This type of design pattern is a creation pattern, which provides the best way to create objects.

In factory mode, when creating objects, we do not expose the creation logic to the client, and point to the newly created objects by using a common interface.

  • **Intent: * * define an interface for creating objects, and let its subclasses decide which factory class to instantiate. The factory mode delays the creation process to the subclasses.
  • **Problems solved: * * mainly solves the problem of interface selection
  • **How to use: * * we explicitly plan to create different instances under different conditions.
  • **Key code: * * the creation process is executed in its subclass.
  • Application example: if you need a car, you can pick up the goods directly from the factory, regardless of how the car is made and the specific implementation in the car.

2. UML diagram:

3. Code implementation

Shape interface
package pri.zsl.jdbc.models.factory;

/**
 * @author m1767
 */
public interface Shape {
    /**
     *Draw shape
     */
    void draw();
}

Circle implementation class
package pri.zsl.jdbc.models.factory;

/**
 * @author m1767
 */
public class Circle implements Shape{

    /**
     * Draw shape
     */
    @Override
    public void draw() {
        System.out.println("circle");
    }
}

Rectangle implementation class
package pri.zsl.jdbc.models.factory;

/**
 * @author m1767
 */
public class Rectangle implements Shape{
    /**
     * Draw shape
     */
    @Override
    public void draw() {
        System.out.println("rectangle!!!!!");
    }
}

Factory class
package pri.zsl.jdbc.models.factory;

/**
 * @author m1767
 */
@SuppressWarnings("all")
public class Factory {

    public static Shape getShape(String name) {
        Shape shape = null;
        switch (name) {
            case "rectangle":
                shape = new Rectangle();
                break;
            default:
                shape = new Circle();
                break;
        }
        return shape;
    }
}

Test test
package pri.zsl.jdbc.models.factory;

/**
 * @author m1767
 */
public class Test {
    public static void main(String[] args) {
        Shape shape = Factory.getShape("rectangle");
        shape.draw();
    }
}

Result display
//rectangle!!!!!

2. Abstract factory mode

1. Concept

Abstract Factory Pattern is to create other factories around a super factory. The super factory is also known as the factory of other factories. This type of design pattern is a creation pattern, which provides the best way to create objects.

In the abstract factory pattern, an interface is a factory responsible for creating a related object, and there is no need to explicitly specify their classes. Each generated factory can provide objects according to the factory pattern.

  • **Intent: * * provides an interface to create a series of related or interdependent objects without specifying their specific classes.

  • **Main solutions: * * mainly solves the problem of interface selection.

  • **When to use: * * the products of the system have more than one product family, and the system only consumes the products of one family.

  • **How to solve this problem: * * define multiple products in a product family.

  • **Application example: * * after work, in order to attend some parties, there must be two or more sets of clothes, such as business clothes (complete set, a series of specific products), fashion clothes (complete set, a series of specific products), and even for a family, there may be business women's clothes, business men's clothes, fashion women's clothes and fashion men's clothes, which are also complete sets, That is, a series of specific products. Assuming a situation (it doesn't exist in reality, otherwise, it can't enter communism, but it is conducive to explaining the abstract factory model), in your home, a wardrobe (specific factory) can only store a certain kind of such clothes (complete sets, a series of specific products), and each time you take this complete set of clothes, you naturally take it out of this wardrobe. Understand with OOP thought that all wardrobe (specific factory) are one of wardrobe (Abstract Factory), and each complete set of clothes includes specific jacket (a specific product) and pants (a specific product). These specific jackets are actually jackets (Abstract products) and specific pants are pants (another abstract product).

2. UML diagram

3. Code implementation

Abstract factory class
package pri.zsl.jdbc.models.abstractfactory;

import pri.zsl.jdbc.models.abstractfactory.color.Color;
import pri.zsl.jdbc.models.abstractfactory.shape.Shape;

/**
 * @author m1767
 */
public abstract class AbFactory {
    /**
     *Gets the Color implementation class
     * @return Color Returns the Color implementation class
     * @param color Color name
     */
    public abstract Color getColor(String color);

    /**
     *Get Shape implementation class
     * @return Shape Return Shape implementation class
     * @param shape Color name
     */
    public abstract Shape getShape(String shape);
}


ShapeFactory factory class
package pri.zsl.jdbc.models.abstractfactory.shape;

import pri.zsl.jdbc.models.abstractfactory.AbFactory;
import pri.zsl.jdbc.models.abstractfactory.color.Color;

/**
 * @author m1767
 */
@SuppressWarnings("all")
public class ShapeFactory extends AbFactory {

    /**
     * Gets the Color implementation class
     *
     * @param color Color name
     * @return Color Returns the Color implementation class
     */
    @Override
    public Color getColor(String color) {
        return null;
    }

    /**
     * Get Shape implementation class
     *
     * @param shape Color name
     * @return Shape Return Shape implementation class
     */
    @Override
    public Shape getShape(String shape) {
        if (shape == null) {
            return null;
        }

        if (shape.equals("rectangle")) {
            return new Rectangle();
        } else {
            return new Circle();
        }
    }
}

ColorFactory factory class
package pri.zsl.jdbc.models.abstractfactory.color;

import pri.zsl.jdbc.models.abstractfactory.AbFactory;
import pri.zsl.jdbc.models.abstractfactory.shape.Shape;

/**
 * @author m1767
 */
public class ColorFactory extends AbFactory {

    /**
     * Gets the Color implementation class
     *
     * @param color Color name
     * @return Color Returns the Color implementation class
     */
    @Override
    public Color getColor(String color) {
        if (color == null) {
            return null;
        }
        if ("red".equals(color)) {
            return new Red();
        }else{
            return new Green();
        }
    }

    /**
     * Get Shape implementation class
     *
     * @param shape Color name
     * @return Shape Return Shape implementation class
     */
    @Override
    public Shape getShape(String shape) {
        return null;
    }
}

Factory manufacturing
package pri.zsl.jdbc.models.abstractfactory;

import pri.zsl.jdbc.models.abstractfactory.color.ColorFactory;
import pri.zsl.jdbc.models.abstractfactory.shape.ShapeFactory;

/**
 * @author m1767
 */
@SuppressWarnings("all")
public class FactoryProducer {

    public static AbFactory getFactory(String choice) {
        if ("color".equalsIgnoreCase(choice)){
            return new ColorFactory();
        }else if ("shape".equalsIgnoreCase(choice)){
            return new ShapeFactory();
        }
        return null;
    }
}

Test test
package pri.zsl.jdbc.models.abstractfactory;

import pri.zsl.jdbc.models.abstractfactory.color.Color;
import pri.zsl.jdbc.models.abstractfactory.shape.Shape;

/**
 * @author m1767
 */
public class Test {
    public static void main(String[] args) {
        // Get Color factory
        AbFactory abFactory = FactoryProducer.getFactory("color");
         // Get Shape factory
        AbFactory abFactory1 = FactoryProducer.getFactory("shape");
        // Get Color subclass
        Color color = abFactory.getColor("red");
         // Get Shape subclass
        Shape shape = abFactory1.getShape("circle");
        shape.draw();
        color.drawColor();
    }
}

Result display
//circle
//red

3. Singleton mode

1. Concept

Singleton Pattern is one of the simplest design patterns in Java. This type of design pattern is a creation pattern, which provides the best way to create objects. This pattern involves a single class that is responsible for creating its own objects while ensuring that only a single object is created. This class provides a way to access its unique object, which can be accessed directly without instantiating the object of this class.

  • matters needing attention

    • 1. A singleton class can only have one instance.
    • 2. A singleton class must create its own unique instance.
    • 3. A singleton class must provide this instance to all other objects.
  • **Intent: * * ensure that a class has only one instance and provide a global access point to access it.

  • **Main solutions: * * a globally used class is frequently created and destroyed.

  • **When to use: * * when you want to control the number of instances and save system resources.

  • **How to solve: * * determine whether the system already has this single instance. If so, return. If not, create it.

  • **Key code: * * constructor is private.

  • Application example:

    • 1. There is only one head teacher in a class.
    • 2. Windows is multi process and multi-threaded. When operating a file, it is inevitable that multiple processes or threads operate a file at the same time, so all files must be processed through a unique instance.
    • 3. Some device managers are often designed in singleton mode. For example, a computer has two printers, which must be processed when outputting. Two printers cannot print the same file.
  • advantage:

    • 1. There is only one instance in memory, which reduces the memory overhead, especially the frequent creation and destruction of instances (such as the homepage page cache of the school of management).
    • 2. Avoid multiple occupation of resources (such as writing files).

2. UML diagram

3. Code implementation

SingleObject class

package pri.zsl.jdbc.models.single;

/**
 * @author m1767
 */
@SuppressWarnings("all")
public class SingleObject {

    private static SingleObject singleObject = new SingleObject();

    private SingleObject(){

    }

    public  static SingleObject getInstance(){
        return singleObject;
    }

    public  void show(){
        System.out.println("hello world!!!");
    }
}

Test test

package pri.zsl.jdbc.models.single;

/**
 * @author m1767
 */
public class Test {
    public static void main(String[] args) {
        SingleObject object = SingleObject.getInstance();
        object.show();
    }
}

Result display

//hello world!!!

4. Adapter mode

1. Concept

	Adapter mode( Adapter Pattern)As a bridge between two incompatible interfaces, this type of design pattern belongs to structural pattern, which combines the functions of two independent interfaces.

This mode involves a single class, which is responsible for adding independent or incompatible interface functions. For example, the card reader is used as the adapter between the memory card and the notebook. You insert the memory card into the card reader and then the card reader into the notebook, so that you can read the memory card through the notebook.

We use the following example to demonstrate the use of adapter mode, in which the audio player device can only play mp3 files, and play vlc and mp4 files by using a more advanced audio player.

  • **Intent: * * convert the interface of a class into another interface desired by the customer. The adapter pattern allows classes that cannot work together because of interface incompatibility to work together.

  • **Main solutions: * * the main solution is that in the software system, some "existing objects" are often put into the new environment, and the interfaces required by the new environment cannot be met by the existing objects.

  • When to use: 1. The system needs to use existing classes, and such interfaces do not meet the needs of the system. 2. You want to create a reusable class to work with some classes that are not closely related to each other, including some classes that may be introduced in the future. These source classes do not necessarily have consistent interfaces. 3. Insert one class into another class family through interface conversion. (for example, tigers and birds, now there is a flying tiger. Without increasing the requirements of entities, an adapter is added to contain a tiger object and realize the flying interface.)

  • **How to solve: * * inheritance or dependency (recommended).

  • **Key code: * * the adapter inherits or relies on existing objects to implement the desired target interface.

  • Application examples: 1. American electric appliance is 110V and China is 220V. There must be an adapter to convert 110V into 220V. 2. JAVA JDK 1.1 provides the Enumeration interface, while 1.2 provides the Iterator interface. If you want to use the 1.2 JDK, you need to convert the Enumeration interface of the previous system into the Iterator interface. At this time, you need the adapter mode. 3. Run WINDOWS program on LINUX. 4. jdbc in JAVA.

  • Advantages: 1. It can let any two classes that are not associated run together. 2. Class reuse is improved. 3. Increased class transparency. 4. Good flexibility.

  • Disadvantages: 1. Excessive use of adapters will make the system very messy and difficult to grasp as A whole. For example, it is obvious that the A interface is called, but in fact, it is internally adapted to the implementation of B interface. If this happens too often in A system, it is tantamount to A disaster. Therefore, if it is not necessary, you can refactor the system directly instead of using adapters. 2. Since JAVA inherits at most one class, at most one adapter class can be adapted, and the target class must be an abstract class.

  • **Usage scenario: * * if you are motivated to modify the interface of a normal system, you should consider using the adapter mode.

  • **Note: * * the adapter is not added during detailed design, but solves the problems of projects in service.

2. URL map

3. Code implementation

##### Advanced media player advanced player interface
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
@SuppressWarnings("all")
public interface AdvancedMediaPlayer {
    public void playVlc(String fileName);
    public void playMp4(String fileName);
}

Mp4Player player
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
public class Mp4Player implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {

    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("Playing mp4 file. Name: "+fileName);
    }
}

VlcPlayer player
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
public class VlcPlayer implements AdvancedMediaPlayer {

    @Override
    public void playVlc(String fileName) {
        System.out.println("Playing vlc file. Name: "+fileName);
    }

    @Override
    public void playMp4(String fileName) {

    }
}

MediaAdapter playback adapter
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
public class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer adapter;

    public  MediaAdapter(String audioType) {
        if ("vlc".equalsIgnoreCase(audioType)){
            adapter = new VlcPlayer();
        }else if("mp4".equalsIgnoreCase(audioType)){
            adapter = new Mp4Player();
        }
    }

    @Override
    public void play(String audioType, String fileName) {
        if ("vlc".equalsIgnoreCase(audioType)) {
            adapter.playVlc(fileName);
        }else if ("mp4".equalsIgnoreCase(audioType)){
            adapter.playMp4(fileName);
        }
    }
}

MediaPlayer media player interface
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
@SuppressWarnings("ALL")
public interface MediaPlayer {
    public void play(String audioType,String fileName);
}
AudioPlayer audio player
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
public class AudioPlayer implements MediaPlayer{
    MediaAdapter mediaAdapter;

    @Override
    public void play(String audioType, String fileName) {
        if ("mp3".equalsIgnoreCase(audioType)){
            System.out.println("Playing mp3 file. Name: "+ fileName);
        }else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)){
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType,fileName);
        }else{
            System.out.println("Invalid media "+audioType+ " format no supported");
        }
    }
}

Test test
package pri.zsl.jdbc.models.adapter;

/**
 * @author m1767
 */
public class Test {

    public static void main(String[] args) {
        AudioPlayer player = new AudioPlayer();
        player.play("mp3", "beyond the horizon.mp3");
        player.play("mp4", "alone.mp4");
        player.play("vlc", "far far away.vlc");
        player.play("avi", "mind me.avi");
    }
}

Result display
/*
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media avi format no supported
*/

Topics: Java Design Pattern Algorithm