Design mode 2 - Korea

1. Seven principles of design mode

1. Purpose

In the process of writing software, programmers are faced with many challenges from coupling, cohesion, maintainability, scalability, reusability, flexibility and so on. The design pattern is to make the program (software) better

(1) Code reusability (i.e. code with the same function does not need to be written many times).

(2) Readability (i.e. programming standardization, which is convenient for other programmers to read and understand).

(3) Scalability (that is, when new functions need to be added, it is very convenient, called maintainability).

(4) Reliability (i.e. when we add new functions, it has no impact on the original functions).

(5) Make the program show the characteristics of high cohesion and low coupling.

Share the golden sentence:

Design patterns contain the essence of object-oriented. "If you understand design patterns, you will understand the essence of object-oriented analysis and design (OOA/D)." Scott Mayers once said in his masterpiece Effective C + +: the difference between a C + + veteran and a C + + novice is that the former has many scars on the back of his hand.

2. Seven principles

The principle of design pattern is actually the principle that programmers should abide by when programming, and it is also the basis of various design patterns (that is, the basis for why design patterns are designed in this way).

Seven principles commonly used in design mode are:

(1) Principle of single responsibility

(2) Interface isolation principle

(3) Dependency inversion (inversion) principle

(4) Richter substitution principle

(5) Opening and closing principle

(6) Dimitt's law

(7) Synthetic Reuse Principle

2. Single responsibility principle

1. Basic introduction

For classes, that is, a class should be responsible for only one responsibility. For example, class A is responsible for two different responsibilities: Responsibility 1 and responsibility 2. When the requirements of responsibility 1 change and change a, the implementation error of responsibility 2 may be caused. Therefore, the granularity of class a needs to be decomposed into class A1 and class A2.

2. Details

(1) Low class complexity, a class is responsible for only one responsibility.

(2) Improve the readability and maintainability of the class.

(3) Reduce the risk caused by changes.

(4) Generally, we should abide by the principle of single responsibility. Only when the logic is simple enough can we violate the principle of single responsibility at the code level; Only if the number of methods in the class is small enough to maintain the principle of single responsibility at the method level.

3. Code

com/atguigu/principle/singleresponsibility/SingleResponsibility1.java

3. Interface Segregation Principle

1. Introduction

The client should not rely on interfaces it does not need, that is, the dependence of one class on another should be based on the smallest interface.

2. Interface isolation principle

(1) Class a depends on class B through interface Interface1, and class C depends on class D through interface Interface1. If interface Interface1 is not the smallest interface for class A and class C, class B and class D must implement methods they do not need.

(2) Interface Interface1 is divided into several independent interfaces, and class A and class C establish dependencies with the interfaces they need respectively. That is, the principle of interface isolation is adopted.

(3) The methods in interface Interface1 are divided into three interfaces according to the actual situation.

3. Code

com/atguigu/principle/segregation/Segregation1.java

4. Dependency Inversion Principle

1. Introduction

(1) High level modules should not rely on low-level modules, and both should rely on their abstraction.

(2) Abstract should not rely on details, details should rely on abstraction.

(3) The central idea of dependency inversion (inversion) is interface oriented programming.

(4) The dependency inversion principle is based on the design concept that abstract things are much more stable than the variability of details. Abstract based architecture is much more stable than detail based architecture. In java, abstraction refers to interfaces or abstract classes, and details are concrete implementation classes.

(5) The purpose of using interfaces or abstract classes is to formulate specifications without involving any specific operations, and hand over the task of showing details to their implementation classes.

2. Details

(1) Low level modules should have abstract classes or interfaces as much as possible, or both, so that the program stability is better.

(2) The declaration type of variables should be abstract classes or interfaces as much as possible, so that there is a buffer layer between our variable references and actual objects, which is conducive to program expansion and optimization.

(3) Follow the principle of Richter substitution when inheriting.

2. Code

com/atguigu/principle/inversion/DependecyInversion.java

5. Liskov Substitution Principle

1. Introduction

Inheritance contains such a layer of meaning: all implemented methods in the parent class are actually setting specifications and contracts. Although it does not force all subclasses to follow these contracts, if subclasses arbitrarily modify these implemented methods, it will damage the whole inheritance system.

Inheritance not only brings convenience to program design, but also brings disadvantages. For example, using inheritance will bring invasiveness to the program, reduce the portability of the program and increase the coupling between objects. If a class is inherited by other classes, when the class needs to be modified, all subclasses must be considered, and after the parent class is modified, all functions involving subclasses may fail

The Liskov Substitution Principle proposed by Ms. Li of MIT is as follows:

If there is object o2 of type T2 for each object o1 of type T1, so that the behavior of program P does not change when all objects o1 are replaced with o2, then type T2 is a subtype of type T1. In other words, all references to the base class must be able to use the objects of its subclasses transparently.

The above Richter substitution principle tells us that when using inheritance, we should follow the Richter substitution principle and try not to rewrite the methods of the parent class in the subclass. At the same time, it also tells us that inheritance actually enhances the coupling of the two classes. Under appropriate circumstances, we can solve the problem through aggregation, composition and dependency.

2. Code

com/atguigu/principle/liskov/improve/Liskov.java

6. Open Closed Principle

1. Introduction

(1) A software entity such as class, module and function should be open to extension (to the provider) and closed to modification (to the user). Build the framework with abstraction and extend the details with implementation.

(2) When the software needs to change, try to realize the change by expanding the behavior of the software entity, rather than by modifying the existing code.

(3) The purpose of following other principles in programming and using design patterns is to follow the opening and closing principles.

2. Case

The function of drawing graphics.

The idea of using the opening and closing principle:

Make the created Shape class into an abstract class and provide an abstract draw method for subclasses to implement. In this way, when we have a new Shape type, we only need to make the new Shape class inherit the Shape and implement the draw method. The user's code does not need to be modified, that is, it meets the opening and closing principle.

3. Code

com/atguigu/principle/ocp/Ocp.java

7. Demeter principle

1. Introduction

(1) One object should have minimal knowledge of other objects.

(2) The closer the relationship between classes, the greater the degree of coupling.

(3) The Demeter principle is also called the least known principle, that is, the less a class knows about the class it depends on, the better. In other words, no matter how complex the dependent class is, try to encapsulate the logic inside the class. No information will be disclosed except the public method provided.

(4) There is a simpler definition of Dimitri's Law: only communicate with direct friends.

(5) Direct friends

Each object will have a coupling relationship with other objects. As long as there is a coupling relationship between two objects, we say that the two objects are friends.

There are many ways of coupling, such as dependency, association, combination, aggregation and so on. Among them, we call the classes that appear in member variables, method parameters and method return values as direct friends, while the classes that appear in local variables are not direct friends. In other words, unfamiliar classes should not appear inside the class in the form of local variables.

2. Details

(1) The core of dimitt's law is to reduce the coupling between classes.

(2) Since each class reduces unnecessary dependencies, dimitt's law only requires reducing the coupling relationship between classes (objects), not requiring no dependencies at all.

3. Code

com/atguigu/principle/demeter/improve/Demeter1.java

8. Composite Reuse Principle

Design principles and core ideas:

(1) Find out what changes may be needed in the application, separate them, and don't mix them with the code that doesn't need to change.

(2) Programming for interfaces, not for implementations.

(3) Strive for loose coupling design between interactive objects.

2. Overview and classification of design patterns

1. Master the level of design pattern

(1) Not long after learning programming, I heard what is design pattern

(2) I have a long time of programming experience. I have written a lot of code, in which design patterns are used, but I don't know

(3) After studying design patterns, I found that I was already using them, and found some new patterns that were very useful

(4) Read a lot of source code and frameworks written by others, see other people's design patterns, and be able to understand the subtlety and benefits of design patterns.

(5) I didn't realize that I used the design pattern and wrote it skillfully.

2. Overview

(1) Design pattern is the useful experience of programmers in the face of similar software engineering design problems. Pattern is not code, but a general solution to a certain kind of problems. Design pattern represents the best practice. These solutions are summarized by many software developers after a long period of trial and error.

(2) The essence of design pattern improves the maintainability, universality and expansibility of software, and reduces the complexity of software.

3. Type

(1) Creation mode: Singleton mode, abstract factory mode, prototype mode, builder mode and factory mode.

(2) Structural mode: adapter mode, bridge mode, decoration mode, combination mode, appearance mode, sharing mode and agent mode.

(3) Behavioral mode: template method mode, command mode, visitor mode, iterator mode, observer mode, mediator mode, memo mode, Interpreter mode, state mode, policy mode and responsibility chain mode (responsibility chain mode).

3. Adapter mode

1. Introduction

1. Overview

Adapter pattern transforms the interface of a class into another interface expected by the client. The main purpose is compatibility, so that two classes that cannot work together due to interface mismatch can work together. Its alias is wrapper.

Adapter mode belongs to structural mode, which is mainly divided into three categories: class adapter mode, object adapter mode and interface adapter mode.

2. Working principle

From the user's point of view, there is no Adaptee, which is decoupled. The user calls the target interface method transformed by the adapter, and then the adapter calls the relevant interface method of the Adaptee.

After receiving the feedback result, the user feels that he is only interacting with the target interface, as shown in the figure:

3. Introduction to use

The Adapter class implements the dst class (target class) interface by inheriting the src class (Adaptee) to complete the adaptation of src - > dst.

2. Case

demand

Take the example of charger in life to explain the Adapter. The charger itself is equivalent to the Adapter, 220V AC is equivalent to src (i.e. the Adaptee), and our target DST (i.e. the target) is 5V DC, which is completed by using the object Adapter mode.

1. Adapted classes

package com.atguigu.adapter.objectadapter;

/**
 * Object adapter - adapted class
 */
public class Voltage220V {
   //Output 220V voltage, unchanged
   public int output220V() {
      int src = 220;
      System.out.println("Voltage=" + src + "Crouch");
      return src;
   }
}

2. Adapter interface

package com.atguigu.adapter.objectadapter;

//Adapter interface
public interface IVoltage5V {
	public int output5V();
}

3. Adapter class

package com.atguigu.adapter.objectadapter;

/**
 * Hold an instance of src class to solve the problem of compatibility. That is, it holds src class and implements dst class interface,
 * Complete the adaptation of SRC - > DST
 */
//The adapter class gets 220v voltage and becomes 5V
public class VoltageAdapter implements IVoltage5V {
   //Holds an instance of the src class
   private Voltage220V voltage220V; // Association - aggregation

   //Pass in a Voltage220V instance through the constructor
   public VoltageAdapter(Voltage220V voltage220v) {
      this.voltage220V = voltage220v;
   }

   @Override
   public int output5V() {
      int dst = 0;
      if (null != voltage220V) {
         int src = voltage220V.output220V();//Obtain 220V voltage
         System.out.println("Use the object adapter for adaptation~~");
         dst = src / 44;
         System.out.println("After adaptation, the output voltage is=" + dst);
      }
      return dst;
   }
}

4. Target usage class

package com.atguigu.adapter.objectadapter;

public class Phone {
   //After the charging adaptation is completed. Pass in an interface that depends on the adapter class Voltage220
   public void charging(IVoltage5V iVoltage5V) {
      if(iVoltage5V.output5V() == 5) {
         System.out.println("The voltage is 5 V, Can charge~~");
      } else if (iVoltage5V.output5V() > 5) {
         System.out.println("Voltage greater than 5 V, Can't charge~~");
      }
   }
}

5. Test class - client

package com.atguigu.adapter.objectadapter;

public class Client {
   public static void main(String[] args) {
      System.out.println(" === Object Adapter Pattern  ====");
      Phone phone = new Phone();
      //Complete the charging task
      phone.charging(new VoltageAdapter(new Voltage220V()));
   }
}

6. Details

(1) The three naming methods are named according to the form src gives to the Adapter (the form in the Adapter).

(2) Object Adapter: given by object, src is held as an object in the Adapter.

4. Decorative pattern

1. Introduction

(1) Overview

Decorator mode: dynamically attach new functions to objects. In terms of object function expansion, it is more flexible than inheritance, and the decorator mode also embodies the open close principle (ocp)

(2) Principle

Decorator mode is like packing an express.

Main body: for example: ceramics, clothes (Component) / / the person to be decorated.

Packaging: for example: newspaper filling, plastic foam, cardboard, and plank (Decorator).

ConcreteComponent: a specific body, such as the previous single coffee.

Between the Component and ConcreteComponent as shown in the figure, if there are many ConcreteComponent classes, you can also design a buffer layer to extract the common parts, and the abstraction layer is a class.

2. Case

Order in decorator mode: 2 chocolate + 1 milk LongBlack

1. Drink class

package com.atguigu.decorator;

/**
 * Decorator mode
 */
public abstract class Drink {
	public String des; // describe
	private float price = 0.0f; //Price

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	//Core method - abstract method of calculating cost
	//Subclass (so that the price can be calculated)
	public abstract float cost();
}

2. coffer class

public class Coffee extends Drink {
	//Single coffee is its price
	@Override
	public float cost() {
		return super.getPrice();
	}
}

3. Single coffee - LongBlack

public class LongBlack extends Coffee {
	public LongBlack() {
		setDes(" longblack ");
		setPrice(5.0f);
	}
}

4. Decorator

//Decorator
public class Decorator extends Drink {
   //Inherit and combine interfaces
   private Drink obj;

   public Decorator(Drink obj) { //combination
      this.obj = obj;
   }

   @Override
   public float cost() {
      // getPrice own price. The structure of single coffee should also be counted
      return super.getPrice() + obj.cost();
   }

   @Override
   public String getDes() {
      // obj.getDes() outputs the information of the decorated person
      return super.des + " " + getPrice() + " && " + obj.getDes();
   }
}

5. Specific decorator

//Specific Decorator, here is the seasoning
public class Chocolate extends Decorator {
   public Chocolate(Drink obj) {
      super(obj);
      setDes(" Chocolates ");
      setPrice(3.0f); // Price of condiment
   }
}

public class Milk extends Decorator {
	public Milk(Drink obj) {
		super(obj);
		setDes(" milk ");
		setPrice(2.0f); 
	}
}

6. Client test

public class Client {
   public static void main(String[] args) {
      //Order in decorator mode: 2 chocolate + 1 milk LongBlack
      //1. Order a LongBlack
      Drink order = new LongBlack();
      System.out.println("Fee 1:" + order.cost());
      System.out.println("Description:" + order.getDes());

      //2. Add a portion of milk to order
      order = new Milk(order);
      //3. Add a chocolate to order
      order = new Chocolate(order);
      //4. Add another chocolate to order
      order = new Chocolate(order);

      // 13 = 5+ 2 + 3 + 3
      System.out.println("Total cost:" + order.cost());
      //Chocolate 3.0 & & Chocolate 3.0 & & milk 2.0 & & longpack
      System.out.println("Description:" + order.getDes());
   }
}

5. Combination mode

1. Introduction

1. Overview

Composite Pattern, also known as partial overall pattern, creates a tree structure of object groups and combines objects into a tree structure to represent the hierarchical relationship of "whole part".

The combination mode makes the user's access to single objects and combined objects consistent, that is, combination allows customers to deal with individual objects and combined objects in a consistent way

2. Schematic diagram

(1) Component: This is the object declaration interface in the composition. If appropriate, it implements the default behavior of the interface common to all classes. It is used to access and manage component subcomponents. Component can be an abstract class or interface.

(2) Leaf: represents a leaf node in a combination, which has no child nodes.

(3) composite: non leaf node, which is used to store sub components and implement related operations of sub components in component, such as adding, deleting, etc.

3. Problems solved

When our object to be processed can generate a tree structure, and we want to operate on the nodes and leaves of the tree, it can provide a consistent way, regardless of whether it is a node or a leaf.

2. Case

1. Demand

Display the department structure of a school, and display the Department composition of the school in one page. A school has multiple colleges and a college has multiple departments.

2. Code

(1) Composite interface class

package com.atguigu.composite;

/**
 * Combination mode
 * organization
 */
public abstract class OrganizationComponent {
   private String name; // name
   private String des; // explain

   //add to
   protected void add(OrganizationComponent organizationComponent) {
      //Default implementation
      throw new UnsupportedOperationException();
   }

   protected void remove(OrganizationComponent organizationComponent) {
      //Default implementation
      throw new UnsupportedOperationException();
   }

   //constructor 
   public OrganizationComponent(String name, String des) {
      super();
      this.name = name;
      this.des = des;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getDes() {
      return des;
   }

   public void setDes(String des) {
      this.des = des;
   }

   //The method print is made abstract, and subclasses need to be implemented
   protected abstract void print();
}

(2) University Class

package com.atguigu.composite;

import java.util.ArrayList;
import java.util.List;

//University is a Composite, which can manage College s
public class University extends OrganizationComponent {
   List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();

   // constructor 
   public University(String name, String des) {
      super(name, des);
   }

   // Override add
   @Override
   protected void add(OrganizationComponent organizationComponent) {
      organizationComponents.add(organizationComponent);
   }

   // Override remove
   @Override
   protected void remove(OrganizationComponent organizationComponent) {
      organizationComponents.remove(organizationComponent);
   }

   @Override
   public String getName() {
      return super.getName();
   }

   @Override
   public String getDes() {
      return super.getDes();
   }
   // The print method is to output the colleges included in the University
   @Override
   protected void print() {
      System.out.println("--------------" + getName() + "--------------");
      //Traverse the organizationComponents (the list set stores the college, and the print() method of the college will be called)
      for (OrganizationComponent organizationComponent : organizationComponents) {
         organizationComponent.print();
      }
   }
}

(3) College class

package com.atguigu.composite;

import java.util.ArrayList;
import java.util.List;

//College Composite
public class College extends OrganizationComponent {
   //Department stored in List
   List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();

   // constructor 
   public College(String name, String des) {
      super(name, des);
   }

   // Override add
   @Override
   protected void add(OrganizationComponent organizationComponent) {
      //In the actual business in the future, the add of college and the add of university are not necessarily the same
      organizationComponents.add(organizationComponent);
   }

   // Override remove
   @Override
   protected void remove(OrganizationComponent organizationComponent) {
      organizationComponents.remove(organizationComponent);
   }

   @Override
   public String getName() {
      return super.getName();
   }

   @Override
   public String getDes() {
      return super.getDes();
   }

   // The print method is to output the colleges included in the University
   @Override
   protected void print() {
      System.out.println("--------------" + getName() + "--------------");
      //Traversing the organizationComponents stores the department, and the print() method of the department will be called
      for (OrganizationComponent organizationComponent : organizationComponents) {
         organizationComponent.print();
      }
   }
}

(4) Professional department

package com.atguigu.composite;
//Family - leaf node leaf
public class Department extends OrganizationComponent {

   //No collection
   public Department(String name, String des) {
      super(name, des);
   }

   //Add and remove do not need to be written because they are leaf nodes
   @Override
   public String getName() {
      return super.getName();
   }

   @Override
   public String getDes() {
      return super.getDes();
   }

   @Override
   protected void print() {
      System.out.println(getName());
   }
}

(5) Client

package com.atguigu.composite;

public class Client {

   public static void main(String[] args) {

      //Creating object schools from large to small
      OrganizationComponent university = new University("Tsinghua University", " Top universities in China ");

      //Create College
      OrganizationComponent computerCollege = new College("school of computing", " school of computing ");
      OrganizationComponent infoEngineercollege = new College("School of Information Engineering", " School of Information Engineering ");


      //Create departments (majors) under each college
      computerCollege.add(new Department("software engineering", " Software engineering is good "));
      computerCollege.add(new Department("Network engineering", " Network engineering is good "));

      infoEngineercollege.add(new Department("communication engineering", " Communication engineering is not easy to learn "));
      infoEngineercollege.add(new Department("Information Engineering", " Information engineering is easy to learn "));

      //Add college to school
      university.add(computerCollege);
      university.add(infoEngineercollege);

      //Printout
      university.print();
//    computerCollege.print();
   }
}

Console output:

--------------Tsinghua University--------------
--------------school of computing--------------
software engineering
 Network engineering
--------------School of Information Engineering--------------
communication engineering
 Information Engineering

3. Details

1. Facilitate the creation of complex hierarchies. The client does not care about the composition details in the composition, and it is easy to add nodes or leaves to create a complex tree structure.

2. When you need to traverse the organization, or the object you are dealing with has a tree structure, it is very suitable to use the combination mode.

3. It requires high abstraction. If there are many differences between nodes and leaves, for example, many methods and attributes are different, it is not suitable to use composite mode.

6. Appearance mode (Facade)

1. Introduction

1. Overview

Facade, also known as "process mode": appearance mode provides a consistent interface for a group of interfaces in the subsystem. This mode defines a high-level interface, which makes the subsystem easier to use.

Appearance mode defines a consistent interface to shield the details of the internal subsystem, so that the caller only needs to call the interface without paying attention to the internal details of the subsystem.

2. Schematic class diagram

(1) Facade: provide a unified calling interface for the caller. The facade knows which subsystems are responsible for processing requests, so as to proxy the caller's requests to appropriate subsystem objects.

(2) Caller (Client): the caller of the appearance interface.

(3) Collection of subsystems: refers to the module or subsystem that handles the tasks assigned by the Facade object. It is the actual provider of functions.

3. Appearance mode to solve Cinema Management

The appearance mode can be understood as converting a group of interfaces. Customers can achieve the goal only by calling one interface instead of multiple interfaces. For example, the restart function of the mobile phone (combining shutdown and startup into one operation).

2. Case

1. Demand

Set up a home theater:
DVD Player, projector, automatic screen, surround sound, popcorn machine,Complete the of using home theater
 Function, the process is:
• Direct use of remote control: coordinate the switch of each equipment
• Popcorn opener
• Drop the screen
• Turn on the projector
• Turn on the stereo
• open DVD,choose dvd
• Go get the popcorn
• Dim light
• play
• After viewing, turn off all kinds of equipment

2. Code

(1)DVDPlayer

package com.atguigu.facade;

public class DVDPlayer {

   //Use singleton mode and hungry Chinese style
   private static DVDPlayer instance = new DVDPlayer();

   public static DVDPlayer getInstanc() {
      return instance;
   }

   public void on() {
      System.out.println(" dvd on ");
   }

   public void off() {
      System.out.println(" dvd off ");
   }

   public void play() {
      System.out.println(" dvd is playing ");
   }

   public void pause() {
      System.out.println(" dvd pause ..");
   }
}

(2) Popcorn popcorn

package com.atguigu.facade;

//popcorn
public class Popcorn {
   private static Popcorn instance = new Popcorn();

   public static Popcorn getInstance() {
      return instance;
   }

   public void on() {
      System.out.println(" popcorn on ");
   }

   public void off() {
      System.out.println(" popcorn ff ");
   }

   public void pop() {
      System.out.println(" popcorn is poping  ");
   }
}

(3) Appearance class

package com.atguigu.facade;

//Make an appearance class in the middle
public class HomeTheaterFacade {
   //Define each subsystem object
   private TheaterLight theaterLight;
   private Popcorn popcorn;
   private Stereo stereo;
   private Projector projector;
   private Screen screen;
   private DVDPlayer dVDPlayer;

   //constructor 
   public HomeTheaterFacade() {
      super(); //Get instance
      this.theaterLight = TheaterLight.getInstance();
      this.popcorn = Popcorn.getInstance();
      this.stereo = Stereo.getInstance();
      this.projector = Projector.getInstance();
      this.screen = Screen.getInstance();
      this.dVDPlayer = DVDPlayer.getInstanc();
   }

   //The operation is divided into four steps
   public void ready() {
      popcorn.on();
      popcorn.pop();
      screen.down();
      projector.on();
      stereo.on();
      dVDPlayer.on();
      theaterLight.dim();
   }

   public void play() {
      dVDPlayer.play();
   }

   public void pause() {
      dVDPlayer.pause();
   }

   public void end() {
      popcorn.off();
      theaterLight.bright();
      screen.up();
      projector.off();
      stereo.off();
      dVDPlayer.off();
   }
}

(4) Caller client

public class Client {
   public static void main(String[] args) {
      HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
      //Get the appearance class and call the method selectively
      homeTheaterFacade.ready();
      homeTheaterFacade.play();
      homeTheaterFacade.end();
   }
}

3. Details

(1) The appearance mode shields the details of the subsystem, so the appearance mode reduces the complexity of the client's use of the subsystem.

(2) The coupling relationship between the client and the subsystem in the appearance mode makes the modules inside the subsystem easier to maintain and expand.

(3) Through the rational use of appearance mode, we can better divide the access level.

(4) When the system needs layered design, Facade mode can be considered.

(5) When maintaining a large legacy system, the system may have become very difficult to maintain and expand. At this time, we can consider developing a Facade class for the new system to provide a clear and simple interface of the legacy system, so that the new system can interact with the Facade class and improve reusability.

(6) You can't use the appearance mode too much or unreasonably. It's better to use the appearance mode or call the module directly. The purpose is to make the system hierarchical and conducive to maintenance.

7. Sharing mode

1. Introduction

1. Overview

Flyweight Pattern is also called fly pattern: it uses sharing technology to effectively support a large number of fine-grained objects.

It is often used in the bottom development of the system to solve the performance problems of the system. Like the database connection pool, there are all created connection objects. Among these connection objects, we can use them directly to avoid re creation. If we don't need them, we can create one.

Shared meta mode can solve the problem of memory waste of repeated objects. When there are a large number of similar objects in the system and a buffer pool is needed. Instead of always creating new objects, you can take them from the buffer pool. This can reduce system memory and improve efficiency at the same time.

2. Schematic class diagram

(1) FlyWeight: an abstract meta role. It is an abstract class of a product and defines the interface or implementation of the external state and internal state of the object.

(2) ConcreteFlyWeight: a specific shared role is a specific product class that implements Abstract role definitions and related businesses.

(3) UnsharedConcreteFlyweight: a role that cannot be shared. Generally, it does not appear in the shared factory.

(4) FlyweightFactory: shared factory class, which is used to create a pool capacity (Collection) and provide methods to get objects from the pool.

3. Internal / external status

The shared meta pattern puts forward two requirements: fine granularity and shared objects. This involves internal state and external state, that is, the information of the object is divided into two parts: internal state and external state.

(1) Internal state refers to the information shared by the object, which is stored in the shared meta object and will not change with the change of the environment.

(2) External state refers to a mark on which an object can depend. It is a state that changes with the environment and cannot be shared.

For example, go has a large number of chess objects, and checkers have more colors, so the color of chess pieces is the internal state of chess pieces; The difference between each piece is the position. When we drop the piece, the color of the piece is fixed, but the position is changed, so the coordinate of the piece is the external state of the piece.

2. Case

1. Demand

For small-scale outsourcing projects, A product display website is built for customer A, and the friends of customer A also want to build such A product display website, but the requirements are somewhat different:

(1) Some customers request to release it in the form of news

(2) A client asked to publish in the form of blog

2. Code

(1) WebSite abstract class

public abstract class WebSite {
   public abstract void use(User user);//Abstract method
}

(2) Specific website

public class ConcreteWebSite extends WebSite {
   //Shared part, internal state
   private String type = ""; //Form (type) of website publishing

   //Constructor - pass in the specific website type
   public ConcreteWebSite(String type) {
      this.type = type;
   }

   @Override
   public void use(User user) {
      System.out.println("The publishing form of the website is:" + type + " In use .. User is" + user.getName());
   }
}

(3) User - external status

public class User {
   private String name;

   public User(String name) {
      super();
      this.name = name;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

(4) Client

public class Client {
   public static void main(String[] args) {
      // Create a factory class
      WebSiteFactory factory = new WebSiteFactory();

      // The customer wants a website to publish in the form of news
      WebSite webSite1 = factory.getWebSiteCategory("Journalism");
      webSite1.use(new User("tom"));

      // The customer wants a website published in the form of blog
      WebSite webSite2 = factory.getWebSiteCategory("Blog");
      webSite2.use(new User("jack"));
      
      System.out.println("Classification of websites=" + factory.getWebSiteCount());
   }
}

3. Details

(1) In this way, "enjoy" means share, and "Yuan" means object.

(2) When there are a large number of objects in the system, which consume a lot of memory, and most of the object states can be externalized, we can consider using the meta mode.

(3) Judge with the unique identification code. If there is in memory, return the object identified by the unique identification code and store it with HashMap/HashTable.

(4) Meta sharing mode greatly reduces the creation of objects, reduces the occupation of program memory and improves efficiency.

(5) The sharing mode increases the complexity of the system. We need to separate the internal state from the external state. The external state has solidification characteristics and should not change with the change of the internal state. This is what we need to pay attention to when using the sharing mode.

(6) When using the shared element mode, pay attention to the division of internal state and external state, and a factory class is required to control it.

(7) The classic application scenario of meta sharing mode is the scenario that requires buffer pool, such as String constant pool and database connection pool.

Tags: Design Pattern

Posted by tarlejh on Fri, 15 Apr 2022 14:39:41 +0930