Design Pattern-Combination Pattern

1 Introduction

In real life, there are many "part-whole" relationships, such as departments and colleges in universities, departments and branches in the head office, books and school bags in school supplies, clothes and wardrobes in daily necessities, and Pots and pans in the kitchen. The same is true in software development, for example, files and folders in the file system, simple controls and container controls in form programs, and so on. The processing of these simple objects and composite objects is very convenient if you use the combined mode to achieve.

2. Definition and characteristics of combination mode

Definition of Composite Pattern: Sometimes it is called Part-Whole pattern. It is a pattern that combines objects into a tree-like hierarchical structure to express the "whole-part" relationship. It allows users to have consistent access to single objects and combined objects, which is a structural design pattern.

The combination mode is generally used to describe the relationship between the whole and the part. It organizes objects into a tree structure. The top node is called the root node. The root node can contain branch nodes and leaf nodes, and the branch node can contain branch nodes. And leaf nodes, the tree structure diagram is as follows

Insert picture description here

As can be seen from the above figure, in fact, the root node and the branch node are essentially the same data type and can be used as a container; while the leaf node and the branch node do not belong to the same type semantically. However, in the combined mode, the branch nodes and leaf nodes are considered to belong to the same data type (defined by a unified interface), so that they have consistent behavior.

In this way, in the combined mode, the objects in the entire tree structure belong to the same type. The advantage is that the user does not need to distinguish whether it is a branch node or a leaf node, and can directly operate, which brings great benefits to the user. convenient.

The main advantages of the combined model are:

  1. The combined mode allows the client code to process a single object and a combined object consistently, without having to care about whether it is a single object or a combined object, which simplifies the client code;
  2. It is easier to add new objects in the assembly, and the client will not change the source code because of adding new objects, which meets the "opening and closing principle";

The main disadvantages are:

  1. The design is more complicated, and the client needs to spend more time clarifying the hierarchical relationship between classes
  2. It is not easy to restrict the components in the container
  3. It is not easy to use inheritance methods to add new features of components

3. The structure and realization of the combined mode

The structure of the combined mode is not very complicated, and its structure and implementation are analyzed below.

The structure of the pattern

The combination mode includes the following main roles:

  1. Abstract component (Component) role: Its main function is to declare public interfaces for leaf and branch components and implement their default behaviors. In the transparent composition mode, the abstract component also declares the interface for accessing and managing subclasses; in the safe composition mode, the interface for accessing and managing subclasses is not declared, and the management work is done by the branch component. (The total abstract class or interface defines some common methods, such as adding and deleting)
  2. Leaf component (Leaf) role: it is a leaf node object in the combination, it has no child nodes, it is used to inherit or implement abstract components
  3. Branch component (Composite) role/intermediate component: It is the branch node object in the combination, it has child nodes, used to inherit and implement abstract components. Its main function is to store and manage sub-components, usually including Add(), Remove(), GetChild() and other methods

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

  1. Transparent way

In this way, because the abstract component declares all the methods in all subclasses, the client does not need to distinguish between the leaf object and the branch object, which is transparent to the client. But its disadvantage is: the leaf component does not originally have Add(), Remove() and GetChild() methods, but they have to be implemented (empty implementation or throwing exceptions), which will bring some security problems. The structure diagram is shown in Figure 1.

Insert picture description here

  1. Safe way

In this way, the method of managing sub-components is moved to the branch component. Abstract components and leaf components have no management method for sub-objects. This avoids the security problem of the previous method, but because the leaves and branches are different The client needs to know the existence of the leaf object and the branch object when calling, so the transparency is lost. The structure diagram is shown in Figure 2.

Insert picture description here

Realization of the pattern

If you want to access the elements in the set c0={leaf1,{leaf2,leaf3}}, the corresponding tree diagram is shown in Figure 3.

Insert picture description here

  1. Transparent 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();
    }
}

//抽象构件
interface Component {
    
    
    public void add(Component c);

    public void remove(Component c);

    public Component getChild(int i);

    public void operation();
}

//树叶构件
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() {
    
    
        System.out.println("树叶" + name + ":被访问!");
    }
}

//树枝构件
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() {
    
    
        for (Object obj : children) {
    
    
            ((Component) obj).operation();
        }
    }
}

Leaf 1: Be visited!
Leaf 2: Be visited!
Leaf 3: Be visited!

  1. Safe combination mode

The implementation code of the safe combination mode is similar to that of the transparent combination mode, as long as you make a simple modification to it, the code is as follows.

First modify the Component code to only retain the public behavior of the hierarchy.

interface Component {
    
    
	public void operation();
}

Then modify the client code to change the type of the branch component to the Composite type in order to obtain methods for managing subclass operations.

public class CompositePattern {
    
    
    public static void main(String[] args) {
    
    
        Composite c0 = new Composite();
        Composite 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();
    }
}

4. Application examples of combination mode

[Example 1] The combination mode is used to realize the function of displaying the information of the products selected by the user after shopping in the store, and calculating the total price of the selected products.

Note: If Mr. Li goes to the daily necessities store in "Tianjie e corner" in Shaoguan, he uses a red small bag to pack 2 packs of Wuyuan specialty products (unit price 7.9 yuan), a map of Wuyuan (unit price 9.9 yuan); use 1 white The small bag contains 2 sachets of Shaoguan Fragrance (RMB 68) and 3 sachets of Shaoguan Black Tea (RMB 180); a middle bag holds the red small bag in front and 1 Jingdezhen porcelain (RMB 380); use 1 A large bag contains the front middle bag, white small bag and a pair of Li-Ning sports shoes (unit price 198 yuan).

The last "big bag" contains: {1 pair of Li Ning brand sneakers (unit price 198 yuan), white small bag {2 pack of Shaoguan mushrooms (unit price 68 yuan), 3 packs of Shaoguan black tea (unit price 180 yuan)}, medium bag {1 Jingdezhen porcelain (unit price 380 yuan), red small bag {2 packages of Wuyuan specialties (unit price 7.9 yuan), 1 Wuyuan map (unit price 9.9 yuan)}}}, now it requires programming to show that Mr. Li puts in the big bag All product information and calculate the total price to be paid.

This example can be designed according to the safe combination mode, and its structure diagram is shown in Figure 4.

Insert picture description here

The program code is as follows:

package composite;

import java.util.ArrayList;

public class ShoppingTest {
    
    
    public static void main(String[] args) {
    
    
        float s = 0;
        Bags BigBag, mediumBag, smallRedBag, smallWhiteBag;
        Goods sp;
        BigBag = new Bags("大袋子");
        mediumBag = new Bags("中袋子");
        smallRedBag = new Bags("红色小袋子");
        smallWhiteBag = new Bags("白色小袋子");
        sp = new Goods("婺源特产", 2, 7.9f);
        smallRedBag.add(sp);
        sp = new Goods("婺源地图", 1, 9.9f);
        smallRedBag.add(sp);
        sp = new Goods("韶关香菇", 2, 68);
        smallWhiteBag.add(sp);
        sp = new Goods("韶关红茶", 3, 180);
        smallWhiteBag.add(sp);
        sp = new Goods("景德镇瓷器", 1, 380);
        mediumBag.add(sp);
        mediumBag.add(smallRedBag);
        sp = new Goods("李宁牌运动鞋", 1, 198);
        BigBag.add(sp);
        BigBag.add(smallWhiteBag);
        BigBag.add(mediumBag);
        System.out.println("您选购的商品有:");
        BigBag.show();
        s = BigBag.calculation();
        System.out.println("要支付的总价是:" + s + "元");
    }
}

//抽象构件:物品
interface Articles {
    
    
    public float calculation(); //计算

    public void show();
}

//树叶构件:商品
class Goods implements Articles {
    
    
    private String name;     //名字
    private int quantity;    //数量
    private float unitPrice; //单价

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

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

    public void show() {
    
    
        System.out.println(name + "(数量:" + quantity + ",单价:" + unitPrice + "元)");
    }
}

//树枝构件:袋子
class Bags implements Articles {
    
    
    private String 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() {
    
    
        float s = 0;
        for (Object obj : bags) {
    
    
            s += ((Articles) obj).calculation();
        }
        return s;
    }

    public void show() {
    
    
        for (Object obj : bags) {
    
    
            ((Articles) obj).show();
        }
    }
}

The goods you purchase are:
Li Ning brand sports shoes (quantity: 1, unit price: 198.0 yuan)
Shaoguan mushroom (quantity: 2, unit price: 68.0 yuan)
Shaoguan black tea (quantity: 3, unit price: 180.0 yuan)
Jingdezhen porcelain (quantity: 1. Unit price: 380.0 yuan)
Wuyuan special product (quantity: 2, unit price: 7.9 yuan)
Wuyuan map (quantity: 1, unit price: 9.9 yuan)
The total price to be paid is: 1279.7 yuan

5. Application scenarios of combined mode

The structure and characteristics of the combined mode are analyzed above, and the following application scenarios to which it is applicable are analyzed below.

  1. Where it is necessary to represent the hierarchical structure of the whole and part of an object
  2. It is required to hide the difference between a combined object and a single object from the user, and the user can use all the objects in the combined structure with a unified interface

6. Extension of Combination Mode

If the leaf node and branch node in the combination mode introduced earlier are abstracted, that is to say, the leaf node and branch node have child nodes, then the combination mode is expanded to a complex combination mode, such as the one in Java AWT/Swing The simple component JTextComponent has subclasses JTextField and JTextArea, and the container component Container also has subclasses Window and Panel. The structure diagram of the complex combination mode is shown in Figure 5.

Insert picture description here

Guess you like

Origin blog.csdn.net/saienenen/article/details/112001638