[TOC]


Design patterns

Learning resources

From b station crazy god said Java design pattern

The seven principles

  1. Open and closed principle: open to expansion, closed to modification.
  2. Richter substitution: Inheritance must ensure that properties held by the superclass are still true in subclasses. Try not to replace methods of the parent class
  3. Dependency inversion principle: Programming-oriented, not implementation-oriented.
  4. Single responsibility principle: Control the size of classes, decouple classes, and improve cohesion.
  5. Interface isolation principle: Create special interfaces for each class that they need.
  6. Demeter’s Rule: Only talk to your “friends,” not strangers.
  7. Rule of composite reuse: Try to use associations such as composition or aggregation first, rather than inheritance and implementation.

Create mode :cat:

The singleton pattern

LanHanShi

public class LazyMan {
    private static LazyMan lazyMan;
    private LazyMan(a){}
    
    public static LazyMan getInstance(a) throws InterruptedException {
        if (lazyMan==null){
            lazyMan=new LazyMan();
        }
        return lazyMan;
    }

   
    public static void main(String[] args) throws InterruptedException {
        /** * thread unsafe a, B enter at the same time ==null * this will result in new singleton creation failed */LazyMan a=LazyMan.getInstance(); LazyMan b=LazyMan.getInstance(); System.out.println(a.hashCode()); System.out.println(b.hashCode()); }}Copy the code

The hungry type

public class Hungry {
    private static Hungry hungry = new Hungry();
    private Hungry(a) {}
    private static Hungry getInstance(a) {
        return hungry;
    }

    public static void main(String[] args) {
        /** * thread safe, but a waste of space * will always take up space if not used */Hungry a=Hungry.getInstance(); Hungry b=Hungry.getInstance(); System.out.println(a.hashCode()); System.out.println(b.hashCode()); }}Copy the code

Double check lock

public class DoubleCheckLock {
Object initialization is divided into three steps * 1, allocate space * 2, create object * 3, point to space * correct step is 123,but maybe exist 132,when a process 13,b return a null object */
    private static DoubleCheckLock doubleCheckLock;

    private DoubleCheckLock(a) {}public static DoubleCheckLock getInstance(a) {
        if (doubleCheckLock == null) {
            synchronized (DoubleCheckLock.class) {
                if (doubleCheckLock == null) {
                    doubleCheckLock = newDoubleCheckLock(); }}}return doubleCheckLock;
    }

    public static void main(String[] args) { DoubleCheckLock a=DoubleCheckLock.getInstance(); DoubleCheckLock b=DoubleCheckLock.getInstance(); System.out.println(a.hashCode()); System.out.println(b.hashCode()); }}/ / the correct version
public class DoubleCheckLock {
    /** * The correct version of volatile prevents reordering of synchronized in the first volatile, and thus ensures the safety of the second if thread */
    private static volatile DoubleCheckLock doubleCheckLock;

    private DoubleCheckLock(a) {}public static DoubleCheckLock getInstance(a) {
        if (doubleCheckLock == null) {
            synchronized (DoubleCheckLock.class) {
                if (doubleCheckLock == null) {
                    doubleCheckLock = newDoubleCheckLock(); }}}return doubleCheckLock;
    }

    public static void main(String[] args) { DoubleCheckLock a=DoubleCheckLock.getInstance(); DoubleCheckLock b=DoubleCheckLock.getInstance(); System.out.println(a.hashCode()); System.out.println(b.hashCode()); }}Copy the code

The enumeration

public enum  EnumF {
    /** * enumeration can guarantee singletons, it is recommended to use * reflection safety */
    INSTANCE;
    private EnumF(a){}
    public static EnumF getInstance(a){
        return INSTANCE;
    }

    public static void main(String[] args) { EnumF a=EnumF.getInstance(); EnumF b=EnumF.getInstance(); System.out.println(a.hashCode()); System.out.println(b.hashCode()); }}Copy the code

Static inner class

public class StaticClass {
    /** * Methods that use static inner classes to access external classes naturally * have reflection, singletons are unsafe */
    private StaticClass(a){}
    public static StaticClass getInstance(a){
        return InnerClass.staticClass;
    }
    private static class InnerClass{
        private static final  StaticClass staticClass= newStaticClass(); }}Copy the code

The factory pattern

The separation of factory, production object, creator and caller does not apply to New. Instead, the factory method is used to select implementation classes and unify object management and control, thus decoupling the caller from our implementor

Simple Factory Mode (Static Factory mode)

Used to create any product in the same hierarchy (for adding new products, existing code needs to be modified)

  1. New objects in the factory by matching strings
  2. Consumers are decoupled from creating objects
  3. You need to modify the string matching of the Factory classViolate the open and close principleMost of the ones that you use, if you have to follow the open and close principle, cost a lot
  4. Easy to call, some object creation is cumbersome
public interface Car {
    void name(a);
}

class Tesla implements Car {
    @Override
    public void name(a) {
        System.out.println("tesla complete"); }}class Wulin implements Car {
    @Override
    public void name(a) {
        System.out.println("wulin complete"); }}class CarFactory {
    public static Car getInstance(String carTypeName) {
        switch (carTypeName) {
            case "wulin":
                return new Wulin();
            case "tesla":
                return new Tesla();
            default:
                return null; }}}class Consumer{
    public static void main(String[] args) {
        Car tesla=CarFactory.getInstance("tesla");
        Car wulin=CarFactory.getInstance("wulin"); tesla.name(); wulin.name(); }}Copy the code

tesla complete
wulin complete
Copy the code

Factory method pattern

Use the factory to produce the same level of fixed products (support to add any products)

  1. In order to comply with the open and closed principle, the new commodity category does not need to modify the factory method, which is more in line with the open and closed principle
  2. For example, Toyota has its own factory, Honda also has its own factory, and new goods need not modify the factory, just need to add a new type of factory, in line with [^ open and close principle, more expansibility]
  3. The number of classes will become so large that one good corresponds to one factory
package factory.method;

public interface Car {
    void name(a);
}

class Tesla implements Car {
    @Override
    public void name(a) {
        System.out.println("tesla complete"); }}class Wulin implements Car {

    @Override
    public void name(a) {
        System.out.println("wulin complete"); }}interface CarFactory {
    Car getCar(a);
}

class WulinCarFactory implements CarFactory {

    @Override
    public  Car getCar(a) {
        return newWulin(); }}class TeslaCarFactory implements CarFactory {

    @Override
    public Car getCar(a) {
        return newTesla(); }}class Consumer {
    public static void main(String[] args) {
        Car wulin =new WulinCarFactory().getCar();
        Car tesla= newTeslaCarFactory().getCar(); wulin.name(); tesla.name(); }}Copy the code

Abstract Factory pattern

Create other factories around a gigafactory, also known as factories of other factories, [^ dolls??]

  1. It’s not nesting dolls, it’s abstract factory patterns, it’s about building a system of products and creating objects in that system

  2. Understand a concept, product family and product grade, e.g. Petrochina produces No. 93 gasoline and natural gas, Sinopec produces No. 93 gasoline and natural gas. The No. 93 gasoline and natural gas produced by Sinopec are a family of products, and the no. 93 gasoline produced by Sinopec and the No. 93 gasoline produced by Sinopec are a product of the same grade

  3. Abstract concrete products into abstract products, abstract products can constitute a family of abstract products, the concrete class of each member of this family is the object to be produced later. Sinopec and CNPC, for example, produce products, the abstract product family is gasoline and natural gas no. 93.

  4. Abstract factories depend on the abstract product family. An abstract factory has n(n equals the number of members of the abstract product family) methods to produce abstract products. Concrete factory classes implement abstract factories that produce products for the corresponding family.

  5. A method is called

    Consumer call

    Abstract Factory Abstract factory object 1=new Concrete product factory ();

    Abstract product 1 Concrete = Abstract factory object 1.get Abstract product 1(); .

    You get a specific product

  6. Disadvantages: If the product family is constantly changing, it is not suitable for this model because frequent modifications are too cumbersome and violate the open and closed principle

  7. Advantages: If you have a mature product family, the Abstract factory pattern is a very powerful pattern to extend the concrete product family and create arbitrary concrete product objects at any time.

package factory.abstractMethod;

< span style = "max-width: 100%; clear: both; min-height: 1em;
public interface IPhoneProduct {
    void sendMessage(a);

    void start(a);
}

interface IComputerProduct {
    void type(a);

    void doSomeOffice(a);
}
// Family of abstract products <

// Apple product family >
class ApplePhoneProduct implements IPhoneProduct {

    @Override
    public void sendMessage(a) {
        System.out.println("IPhone is texting.");
    }

    @Override
    public void start(a) {
        System.out.println("The iPhone is on."); }}class MakBookProduct implements IComputerProduct {
    @Override
    public void type(a) {
        System.out.println("The macBook typing");
    }

    @Override
    public void doSomeOffice(a) {
        System.out.println("The macBook office"); }}// Apple product family <

// Xiaomi product family >

/** * 🐖 just ordered K30S, a little excited */
class K30S implements IPhoneProduct {
    @Override
    public void sendMessage(a) {
        System.out.println("Xiaomi is sending text messages.");
    }

    @Override
    public void start(a) {
        System.out.println("Xiaomi's turned on."); }}class XiaomiBook implements IComputerProduct {
    @Override
    public void type(a) {
        System.out.println("Xiaomi laptop typed.");
    }

    @Override
    public void doSomeOffice(a) {
        System.out.println("Xiaomi Laptop Office"); }}// Xiaomi specific product family <

// Abstract factory >
/** * Abstract factories depend on the abstract product family */
interface AbstractFactory {
    IPhoneProduct getPhone(a);

    IComputerProduct getComputer(a);
}
// Abstract factory <

// Apple factory >

/** * Concrete factories that inherit abstract factories depend on concrete product families that inherit abstract product families * concrete product factories are responsible for producing concrete products */
class AppleFactory implements AbstractFactory{
    @Override
    public IPhoneProduct getPhone(a) {
        return new ApplePhoneProduct();
    }

    @Override
    public IComputerProduct getComputer(a) {
        return newMakBookProduct(); }}// Apple specific factory <

// Xiaomi factory >
class XiaomiFactory implements AbstractFactory{
    @Override
    public IPhoneProduct getPhone(a) {
        return new K30S();
    }

    @Override
    public IComputerProduct getComputer(a) {
        return newXiaomiBook(); }}// Xiaomi's factory <

// Consumer >
class Client{
    public static void main(String[] args) {
        // Create concrete factory abstract factory - concrete family factory polymorphism
        AbstractFactory appleFactory = new AppleFactory();
        AbstractFactory xiaomiFactory = new XiaomiFactory();

        Abstract product -> Concrete product polymorphismIPhoneProduct iPhone=appleFactory.getPhone(); IComputerProduct mac=appleFactory.getComputer(); IPhoneProduct k30S=xiaomiFactory.getPhone(); IComputerProduct xiaomiBook=xiaomiFactory.getComputer(); iPhone.start(); iPhone.sendMessage(); mac.doSomeOffice(); mac.type(); k30S.start(); k30S.sendMessage(); xiaomiBook.type(); xiaomiBook.doSomeOffice(); }}// consumer <
Copy the code
Factory Mode Category Summary (differences)
Simple Factory Mode (Static Factory mode) 1. Applicable to products of the same level, modification will violate the open and closed principle, but because of its simplicity and ease of use, this mode is most used
Abstract method 1. Applicable to products of the same level, the modification will not affect the open and closed principle, but will increase the number of classes
Abstract Factory pattern 1. Used in product family (products), can not frequently modify the members of the product family, but can easily introduce new product system. 2. The first two are products of the same level, which are lines. Abstract factory is the production of a system of family products, is the surface. 3. I prefer to call the Abstract factory model the Abstract family product factory model; Abstract products are abstract family (system) products; Specific products are specific family (system) products; Abstract factories are abstract factories that depend on abstract family products and have n (n= the number of members of abstract family products) methods. A concrete factory is a concrete factory that depends on a concrete product and inherits an abstract factory.

Builder model

Builder mode is also a type of creator mode, providing the best way to create objects, complex objects, different representations

The producer makes the parts, the builder builds the parts.



Copy the code

The prototype pattern



Copy the code

Structural model: CAT2:

Adapter mode