Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

  • 23 design modes for shorthand
  • The singleton pattern
  • Factory Method pattern
  • Abstract Factory pattern
  • The Builder/Builder pattern
  • Prototype mode
  • Flyweight mode
  • The facade pattern
  • Adapter mode
  • Decorator pattern
  • Observer mode
  • Strategy mode
  • Bridge mode
  • The Template Method pattern
  • The Chain of Responsibility model
  • Updates continue at……

Here are 23 design patterns to memorize quicklyPortfolio modelRelated content.

The schema definition

Group objects into a tree structure to represent a partial-whole hierarchy. The composite pattern makes the use of single objects and composite objects consistent.

The combination mode is divided into transparent combination mode and safe combination mode.

Transparent way

In this way, because the abstract component declares all methods in all subclasses, the client does not need to distinguish between leaf and branch objects and is transparent to the client. The downside, however, is that implementing the Add(), Remove(), and GetChild() methods of the leaf component without them (empty implementation or throwing exceptions) poses some security issues.

Safe way

In this way, the management method of child components will be moved to the branch component, component abstract component and leaves no child object management method, a way on this avoids the security issues, but as a result of leaf and branch has a different interface, the client should know when calling the existence of the leaves and branches object, so lost its transparency.

Problem solved

It blurs the concept of simple and complex elements in our tree structure problem, and the client program can handle complex elements as if they were simple elements, thus decoupling the client from the internal structure of complex elements.

Patterns of

To compose (a role). role
Abstract Component roles Its main role is to declare common interfaces for leaf and branch components and implement their default behavior. Abstract artifacts also declare interfaces to access and manage subclasses in a transparent composition pattern; Interfaces that access and manage subclasses are not declared in the secure composite mode; management is done by branch components.
Leaf component (Leaf) roles Is a leaf node object in a composite that has no child nodes and is used to implement the public interface declared in the abstract artifact role.
Composite role Is a branch node object in a composition that has child nodes. It implements the interface declared in the abstract component role, and its main role is to store and manage child widgets, usually including methods Add(), Remove(), GetChild(), and so on.

Pattern implementation

If you want to access the elements in the set c0={leaf1,{leaf2,leaf3}}, the corresponding tree graph is as follows:

package com.niuh.designpattern.composite.v1;

import java.util.ArrayList;

/** * combination mode */
public class CompositePattern {

    public static void main(String[] args) {
        Component c0 = new Composite();
        Component c1 = new Composite();
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");
        Component leaf3 = new Leaf("3"); c0.add(leaf1); c0.add(c1); c1.add(leaf2); c1.add(leaf3); c0.operation(); }}// The abstract component
interface Component {
    void add(Component c);

    void remove(Component c);

    Component getChild(int i);

    void operation(a);
}

// leaves
class Leaf implements Component {
    private String name;

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

    public void add(Component c) {}public void remove(Component c) {}public Component getChild(int i) {
        return null;
    }

    public void operation(a) {
        System.out.println("The leaves" + name + ": Visited!"); }}// A branch member
class Composite implements Component {
    private ArrayList<Component> children = new ArrayList<Component>();

    public void add(Component c) {
        children.add(c);
    }

    public void remove(Component c) {
        children.remove(c);
    }

    public Component getChild(int i) {
        return children.get(i);
    }

    public void operation(a) {
        for(Object obj : children) { ((Component) obj).operation(); }}}Copy the code

The following output is displayed:

The leaves1: Visited! The leaves2: Visited! The leaves3: Visited!Copy the code

Example is given to illustrate

Instance profiles

The combination mode is used to display the information of the selected goods and calculate the total price of the selected goods.

Description: Next door Lao Wang traveled to Nanjing, shopping in the supermarket with a small red bag packed with 2 packages of Nanjing specialty (7.9 yuan), a map of Nanjing (9.9 yuan); Two packets of incense (68 yuan) and three packets of black tea (180 yuan) were packed in a small white bag. A small red bag in the front and a yuhua stone pendant (380 yuan) in a middle bag; With a big bag in front of the middle bag, a small white bag and a pair of Li Ning brand sports shoes (198 yuan).

Finally, the contents of the “big bag” are as follows. Now the program is required to display the information of all commodities put in the big bag by Lao Wang next door and calculate the total price to be paid.

Using the step

It can be designed according to the safety combination mode, and its structure diagram is as follows:

Step 1: Define the Abstract Component roles: objects

interface Articles {
    float calculation(a); / / calculate
    void show(a);
}
Copy the code

Step 2: Define the Leaf artifact (Leaf) role: commodity

class Goods implements Articles {
    private String name;     / / name
    private int quantity;    / / the number of
    private float unitPrice; / / unit price

    public Goods(String name, int quantity, float unitPrice) {
        this.name = name;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }

    public float calculation(a) {
        return quantity * unitPrice;
    }

    public void show(a) {
        System.out.println(name + "(Quantity:" + quantity + Unit price: + unitPrice + "Yuan)"); }}Copy the code

Step 3: Define the Composite role: bag

class Bags implements Articles {
    private String name;     / / name
    private ArrayList<Articles> bags = new ArrayList<Articles>();

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

    public void add(Articles c) {
        bags.add(c);
    }

    public void remove(Articles c) {
        bags.remove(c);
    }

    public Articles getChild(int i) {
        return bags.get(i);
    }

    public float calculation(a) {
        float s = 0;
        for (Object obj : bags) {
            s += ((Articles) obj).calculation();
        }
        return s;
    }

    public void show(a) {
        for(Object obj : bags) { ((Articles) obj).show(); }}}Copy the code

Step 4: Calculate the total payment

public class CompositePattern {

    public static void main(String[] args) {
        float s = 0;
        Bags BigBag, mediumBag, smallRedBag, smallWhiteBag;
        Goods sp;
        BigBag = new Bags("Big bag");
        mediumBag = new Bags("Middle bag");
        smallRedBag = new Bags("Little red bag");
        smallWhiteBag = new Bags("Little white bag");
        sp = new Goods("Specialty of Nanjing".2.7.9 f);
        smallRedBag.add(sp);
        sp = new Goods("Map of Nanjing".1.9.9 f);
        smallRedBag.add(sp);
        sp = new Goods("Mushroom".2.68);
        smallWhiteBag.add(sp);
        sp = new Goods("Black tea".3.180);
        smallWhiteBag.add(sp);
        sp = new Goods("Rain flower stone Pendant".1.380);
        mediumBag.add(sp);
        mediumBag.add(smallRedBag);
        sp = new Goods("Li Ning Sneakers".1.198);
        BigBag.add(sp);
        BigBag.add(smallWhiteBag);
        BigBag.add(mediumBag);
        System.out.println("Lao Wang next door buys:");
        BigBag.show();
        s = BigBag.calculation();
        System.out.println("The total price to be paid is:" + s + "Yuan"); }}Copy the code

The output

The goods Lao Wang buys next door are: Li Ning brand sneakers (Unit:1, the unit price:198.0Yuan) Mushroom (Quantity:2, the unit price:68.0Yuan) Black tea (Quantity:3, the unit price:180.0Yuhua Stone Pendant (Quantity:1, the unit price:380.0Nanjing specialty (Quantity:2, the unit price:7.9Map of Nanjing (Quantity:1, the unit price:9.9The total price to be paid is:1279.7yuanCopy the code

advantages

  1. The composite pattern simplifies client code by allowing it to work consistently with both single and composite objects without caring whether it is working with a single object or a composite object.
  2. It is easier to add new objects into the composition body, and the client will not change the source code because of adding new objects, which meets the “open and close principle”.

disadvantages

  1. The design is more complex, and the client needs to spend more time sorting out the hierarchical relationships between classes.
  2. It is not easy to restrict components in containers;
  3. It is not easy to add new functions to components by inheritance.

Application scenarios

  1. Where a hierarchy of whole and parts of an object needs to be represented.
  2. Where the differences between a composite object and a single object are required to be hidden from the user, and the user can use all objects in the composite structure with a unified interface.

Part, whole scene, such as tree menu, file, folder management.

Application in source code

  • Composite patterns in java.awT
  • Composite patterns in Java collections
  • Mybatis Combination mode in SqlNode

Composite patterns in java.awT

There are two types of Java GUI:

  • AWT(Abstract Window Toolkit) : Abstract Window tool set, is the first generation of Java GUI components. Drawing depends on the underlying operating system. The basic AWT library handles user interface elements by delegating their creation and behavior to native GUI tools on each target platform (Windows, Unix, Macintosh, and so on).
  • Swing, independent of the low-level details, is a lightweight component. Now it is mostly based on Swing development.

Let’s take a look at a simple AWT case:

package com.niuh.designpattern.composite.v3;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/** * the combined mode in java.awt */
public class MyFrame extends Frame {

    public MyFrame(String title) {
        super(title);
    }

    public static void main(String[] args) {
        MyFrame frame = new MyFrame("Frame for composite mode");

        // Define three components to add to Frame
        Button button = new Button("Button A");
        Label label = new Label("This is an AWT Label!");
        TextField textField = new TextField("This is an AWT TextField!");

        frame.add(button, BorderLayout.EAST);
        frame.add(label, BorderLayout.SOUTH);
        frame.add(textField, BorderLayout.NORTH);

        // Define a Panel, add three components to the Panel, and then add the Panel to the Frame
        Panel panel = new Panel();
        panel.setBackground(Color.pink);

        Label lable1 = new Label("Username");
        TextField textField1 = new TextField("Please enter user name:".20);
        Button button1 = new Button("Sure");
        panel.add(lable1);
        panel.add(textField1);
        panel.add(button1);

        frame.add(panel, BorderLayout.CENTER);

        // Set the Frame properties
        frame.setSize(500.300);
        frame.setBackground(Color.orange);
        // Set the click close event
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0); }}); frame.setVisible(true); }}Copy the code

After running, the form will display as follows:

We added three different components: Button, Label and TextField to the Frame container. We also added a Panel container. Panel container added three components: Button, Label and TextField. Why can Frame and Panel containers add different types of components and containers?

Class diagram of the AWT Component

GUI components can be divided into two types based on their role: base components and container components.

  • Basic components, also known as artifacts, are graphical interface elements such as buttons and text boxes.
  • A container is a special component that can hold other components, such as Windows, dialogs, and so on. All container classes arejava.awt.ContainerA direct or indirect subclass of

The code for the Container parent class is as follows:

public class Container extends Component {
    /**
     * The components in this container.
     * @see #add
     * @see #getComponents
     */
    private java.util.List<Component> component = new ArrayList<>();
    
    public Component add(Component comp) {
        addImpl(comp, null, -1);
        return comp;
    }
    / / to omit...
}

Copy the code

Container defines a collection of Component objects. Container and basic components such as Button, Label, and TextField are subclasses of Component. So you can clearly see that the composite pattern is applied here.

The Component class encapsulates common Component methods and properties, such as graphic Component objects, sizes, display positions, foreground and background colors, boundaries, and visibility. Therefore, many Component classes inherit Component methods and variables. The corresponding member methods include:

getComponentAt(int x, int y)
getFont()
getForeground()
getName()
getSize()
paint(Graphics g)
repaint()
update()
setVisible(boolean b)
setSize(Dimension d)
setName(String name)
Copy the code

Composite patterns in Java collections

HashMap provides putAll’s method for putting another Map object into its own storage space and overwriting the value of the previous key if it has the same key value.

package com.niuh.designpattern.composite.v3;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class HashMapTest {

    public static void main(String[] args) {
        Map<String, Integer> map1 = new HashMap<String, Integer>();
        map1.put("aa".1);
        map1.put("bb".2);
        map1.put("cc".3);
        System.out.println("map1: " + map1);

        Map<String, Integer> map2 = new LinkedHashMap<>();
        map2.put("cc".4);
        map2.put("dd".5);
        System.out.println("map2: " + map2);

        map1.putAll(map2);
        System.out.println("map1.putAll(map2): "+ map1); }}Copy the code

The following output is displayed:

map1: {aa=1, bb=2, cc=3}
map2: {cc=4, dd=5}
map1.putAll(map2): {aa=1, bb=2, cc=4, dd=5}
Copy the code

Check putAll source code

public void putAll(Map<? extends K, ? extends V> m) {
		putMapEntries(m, true);
}
Copy the code

The parameters putAll receives are of the parent class Map type, so HashMap is a container class, and Map’s subclasses are leaf classes. Of course, if other subclasses of Map also implement putAll methods, then they are both container classes and leaf classes.

Similarly, addAll(Collection
c) method is also an application of the composite pattern.

Mybatis Combination mode in SqlNode

One of the most powerful features of MyBatis is its dynamic SQL, which can be combined into very flexible SQL statements through if, Choose, when, otherwise, trim, where, set, foreach tags, thus improving the efficiency of developers.

Dynamic SQL — IF

<select id="findActiveBlogLike"  resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’ 
  <if test="title ! = null">
    AND title like #{title}
  </if>
  <if test="author ! = null and author.name ! = null">
    AND author_name like #{author.name}
  </if>
</select>
Copy the code

Dynamic SQL – Choose, when, otherwise

<select id="findActiveBlogLike"  resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title ! = null">
      AND title like #{title}
    </when>
    <when test="author ! = null and author.name ! = null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

Copy the code

Dynamic SQL — WHERE

<select id="findActiveBlogLike"  resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state ! = null">
         state = #{state}
    </if> 
    <if test="title ! = null">
        AND title like #{title}
    </if>
    <if test="author ! = null and author.name ! = null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
Copy the code

Dynamic SQL — foreach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT * FROM POST P WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
Copy the code

When Mybatis processes dynamic SQL nodes, it applies the combined design mode. Mybatis will parse the dynamic SQL nodes and text nodes defined in the mapping configuration file into the corresponding SqlNode implementation, and form a tree structure.

DynamicContext is used to record fragments of SQL statements generated after dynamic SQL statements are parsed. It can be considered as a container for recording the results of dynamic SQL statement parsing.

Abstract component for SqlNode interface, source code as follows

public interface SqlNode {
  boolean apply(DynamicContext context);
}
Copy the code

Apply is the only method defined in the SQLNode interface that parses the dynamic SQL node recorded by the SQLNode based on arguments passed in by the user. And call DynamicContext. AppendSql () method will be parsed SQL fragment appended to DynamicContext. SqlBuilder save, when SQL nodes under all SqlNode parse finished, We can get a dynamically produced, complete SQL statement from DynamicContext and look at the source of the MixedSqlNode class

public class MixedSqlNode implements SqlNode {
  private List<SqlNode> contents;
  public MixedSqlNode(List<SqlNode> contents) {
    this.contents = contents;
  }
  @Override
  public boolean apply(DynamicContext context) {
    for (SqlNode sqlNode : contents) {
      sqlNode.apply(context);
    }
    return true; }}Copy the code

MixedSqlNode maintains a List of type List

used to store SqlNode objects. The apply method iterates through contents through a for loop and calls the apply method on the object. Much like the print method in the Folder class in our example, it is clear that MixedSqlNode plays the role of container artifact.

The functionality of other SqlNode subclasses is briefly summarized as follows:

  • TextSqlNode: containsThe ${}Placeholder dynamic SQL nodes, whose apply method is usedGenericTokenParserparsingThe ${}Placeholder and directly replace the actual parameter value given by the user
  • IfSqlNode: corresponds to dynamic SQL nodes<If>Node, whose apply method passes firstExpressionEvaluator.evaluateBoolean()Method tests whether its test expression is true and, based on the result of the test expression, decides whether to apply() to its children
  • TrimSqlNode: The system adds or deletes the corresponding prefix or suffix based on the resolution result of the child node.
  • WhereSqlNodeSetSqlNodeAll inheritedTrimSqlNode
  • ForeachSqlNode: the corresponding<foreach>Tag to iterate over the collection
  • In dynamic SQL<choose>,<when>,<otherwise>Separately resolved intoChooseSqlNode,IfSqlNode,MixedSqlNode

To sum up, SqlNode interface has multiple implementation classes, each implementation class corresponds to a dynamic SQL node, where SqlNode plays the role of abstract component, MixedSqlNode plays the role of container component, the other is generally leaf component role.

PS: The above code is submitted to Github: github.com/Niuh-Study/…

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy