This is the 12th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge

Java design pattern – appearance pattern after the combination of patterns it also come oh, let’s take a look at it!! 😁 will when review ya, will not come to see it together.

Like a sentence: “eight hours for life, eight hours for development”.

If you like it, let's stick to it!!

‘😁

In the early summer when

One, foreword

1) Introduction:

In real life, there are many “part-whole” relationships, such as departments and colleges in universities, departments and branches in head offices, books and bags in school supplies, clothes and closets in daily necessities, and POTS and pans in kitchens.

The same is true in software development, such as files and folders in file systems, simple controls and container controls in form programs. For these simple objects and composite objects, it is convenient to implement the composite pattern.

2) Overview:

Composite Pattern: Grouping objects into tree structures to represent a “part whole” hierarchy. The composition pattern enables users to use individual and composite objects consistently.

Sometimes called the partial-whole pattern, it allows us to blur the concept of simple and complex elements in our tree structure problem, allowing the client to treat the complex elements as if they were simple, thus decoupling the client from the internal structure of the complex elements.

3) Roles:

The root node Component is an object declaration interface in a composition that, where appropriate, implements the default behavior of an interface shared by all classes. Declare an interface for accessing and managing Component children.

2. The Composite defines the behavior of the branch point, which is used to store the sub-parts. The operations related to the sub-parts are implemented in the Component interface, such as add and remove.

The Leaf node represents the Leaf node object in the combination. The Leaf node has no children.

4) Application scenario:

1. You want to represent the partial-whole hierarchy of objects

2. You want the user to ignore the difference between a composite object and a single object and use all the objects in the composite structure uniformly.

Combination mode is based on the tree structure, so the use of combination mode is mostly where the tree structure appears.

For example: file directory display, multi-level directory rendering tree structure data operation.

Two, code implementation

Case study:

In the following figure, we often see similar menus when accessing other management systems. A menu can contain either a menu item (a menu item is a menu item that contains nothing else) or a menu with other menu items, so it is appropriate to use the combination pattern to describe a menu. Our requirement is to print out the names of all the menus and menu items in a menu.

To implement this case, let’s draw a class diagram:

Code:

Both menus and menu items should inherit from a unified interface, which we’ll call a menu component.

// Menu components should inherit this class, whether they are menus or menu items
public abstract class MenuComponent {

    protected String name;
    protected int level;

    // Add menu
    public void add(MenuComponent menuComponent){
        System.out.println("File cannot add menu");
        throw new UnsupportedOperationException();
    }

    // Remove the menu
    public void remove(MenuComponent menuComponent){
        System.out.println("File cannot be removed menu");
        throw new UnsupportedOperationException();
    }

    // Get the specified submenu
    public MenuComponent getChild(int i){
        System.out.println("File has no submenu");
        throw new UnsupportedOperationException();
    }

    // Get the menu name
    public String getName(a){
        return name;
    }

    public void print(a){
        throw newUnsupportedOperationException(); }}Copy the code

MenuComponent here is defined as an abstract class, because there are common properties and behaviors to implement in the class, so the Menu and MenuItem classes can override only the methods they are interested in, leaving out the methods they don’t need or are not interested in.

For example, the Menu class can contain submenus, so the add(), remove(), and getChild() methods need to be overridden, but MenuItem should not have these methods.

What I’m doing here is printing a sentence and throwing an exception.

Menu

The Menu class already implements all the methods except the getName method, because the Menu class has the ability to add menus, remove menus, and get submenus.

public class Menu extends MenuComponent {

    private List<MenuComponent> menuComponentList;

    public Menu(String name,int level){
        this.level = level;
        this.name = name;
        menuComponentList = new ArrayList<MenuComponent>();
    }

    @Override
    public void add(MenuComponent menuComponent) {
        menuComponentList.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponentList.remove(menuComponent);
    }

    @Override
    public MenuComponent getChild(int i) {
        return menuComponentList.get(i);
    }

    @Override
    public void print(a) {

        for (int i = 1; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
        for(MenuComponent menuComponent : menuComponentList) { menuComponent.print(); }}}Copy the code

MenuItem

A MenuItem is a MenuItem, and there can be no submenus, so the ability to add a menu, remove a menu, and get a submenu is not implemented.

public class MenuItem extends MenuComponent {

    public MenuItem(String name,int level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void print(a) {
        for (int i = 1; i < level; i++) {
            System.out.print("--"); } System.out.println(name); }}Copy the code

test

public class Client {

    public static void main(String[] args) {
        MenuComponent component = new Menu("crush".2);
        MenuComponent c2 = new Menu("wyh1".1);
        MenuComponent wyh4 = new MenuItem("wyh4".2);
        MenuComponent wyh5 = new MenuItem("wyh5".2);

        component.add(c2);

        component.add(wyh4);
        //wyh4.add(wyh5);

        component.print();	
        /** * Output: * --crush * wyh1 * --wyh4 */}}Copy the code

The above code case is a transparent pattern in the composite pattern, you read correctly, there are two kinds of composite patterns. I forgot to write it in front, here to introduce it to you:

  • Transparent combination pattern

    In the transparent composition pattern, all the methods used to manage member objects are declared in the abstract root node role, such as the Add, Remove, and getChild methods declared in the MenuComponent example. This has the advantage of ensuring that all component classes have the same interface. Transparent composite patterns are also the standard form of composite patterns.

    The drawback of the transparent composition mode is that it is not safe, because leaf objects and container objects are fundamentally different. Leaf objects cannot have objects at the next level, that is, they cannot contain member objects. Therefore, it is meaningless to provide methods such as add(), remove(), etc., which will not fail at compile time. But at run time these methods may fail if they are called (if no corresponding error handling code is provided)

  • Safe combination mode

    In the secure composition pattern, no methods for managing member objects are declared in the abstract component role, but they are declared and implemented in the Menu class of the branch node. The drawback of the secure composition pattern is that it is not transparent, because leaf and container components have different methods, and the methods used to manage member objects in the container components are not defined in the abstract component class. Therefore, the client cannot program for abstraction completely, and must treat leaf and container components differently.

Third, summary

advantages

  • Composite patterns mask hierarchical differences in object systems (tree nodes and leaf nodes are of different types), decouple client code from complex container objects, allow clients to ignore hierarchical differences, simplify client code, and use consistent behavior to control different layers. High level module calls are simple.
  • In combination mode, tree node and leaf node objects can be added conveniently, and the existing class library is not invaded, which conforms to the open closed principle.

disadvantages

  • If the class system (tree structure) is too large, the client needs to spend time sorting out the hierarchical relationships between classes, even though it provides consistent operations across different levels;
  • When the composite pattern is used, its leaves and branches are declared as implementation classes, not interfaces, violating the dependency inversion principle.
  • It is not easy to use inheritance methods to add new features to components;

Talk to yourself

You roll me roll, everybody roll, when will this road end. 😇 (or go straight to heaven)

Sometimes I want to stop and have a rest. I have been doing one thing, and I feel hard to stick to it. 😁

Hello, if you happen to see this article and think it’s good for you, please give it a like and let me feel the joy of sharing, Crab. 🤗

If there is an error in writing, please do not add to the instruction!!

Similarly, if there is any doubt, please leave a message or a private message, we will reply to you in the first time.

Under continuous update