Writing in the front

  • Take notes on learning design patterns
  • Improve flexibility in the use of design patterns

Learning to address



Refer to the article


Project source https://gitee.com/zhuang-kang/DesignPattern

16. Combinatorial mode

16.1 Definition and characteristics of composite patterns

Definition of Composite Pattern: Sometimes also called the part-whole Pattern, it is a Pattern that combines objects into a tree-like hierarchical structure, which is used to represent the “whole-part” relationship, and enables users to have consistent access to a single object and a Composite object. It belongs to the structural design Pattern.

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

As can be seen from the figure above, root node and branch node are essentially the same data type and can be used as containers. The leaf node and the branch node do not belong to the same type semantically. However, in the composite mode, the branch node and leaf node are treated as belonging to the same data type (defined by a common interface), making them behave in a consistent way.

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

The main advantages of the composite pattern are:

  1. The composite pattern simplifies client code by allowing it to work consistently with individual and composite objects, regardless of whether it is working with a single object or a composite object.
  2. It is easier to add new objects into the composite body, and the client will not change the source code because of the addition of new objects, satisfying the “Open Closed Principle”;

Its main disadvantages are:

  1. The design is complex, and the client needs to spend more time sorting out the hierarchical relationship between classes;
  2. It is not easy to restrict the artifacts in the container;
  3. It is not easy to use inheritance method to add new functions of components;

16.2 Structure and implementation of composite patterns

16.2.1 Structure of composite patterns

  1. The abstract Component role: Its main role is to declare a common interface for the leaf and branch components and implement their default behavior. In the transparent composition pattern, the abstract component also declares an interface to access and manage subclasses; In the secure composite mode, no interfaces are declared to access and manage subclasses; the management is done by the branch component. (General abstract class or interface, define some common methods, such as add, delete)
  2. A Leaf component (Leaf) role: A Leaf node object in a composition that has no child nodes and is used to inherit or implement an abstract component.
  3. Composite role/intermediate component: A branch node object in a Composite that has child nodes for inheriting and implementing abstract components. Its main purpose is to store and manage child widgets, usually including methods like Add(), Remove(), getChild (), and so on.

16.2.2 Code implementation

As shown in the figure below, we can often see a similar menu when accessing some other management systems. A menu can contain menu items (a menu item is a menu item that contains nothing else) or a menu with other menu items, so it is appropriate to use a combined mode to describe a menu. For a menu, we need to print out all the menus that it contains and the names of the menu items.

MenuComponent is defined as an abstract class. Since there are common properties and behaviors to be implemented in the class, the Menu and MenuItem classes can override only the methods they are interested in, and not the methods they do not need or are not interested in. For example, the Menu class can contain submenus. So you need to override the add(), remove(), and getChild() methods, but MenuItem should not have those methods. The default implementation given here is to throw an exception, but you can change the default implementation to suit your needs.

package com.zhuang.combination; /** * @ClassName MenuComponent * @Description * @Date 2021/3/24 17:02 * @Created by Dell */ public abstract class MenuComponent {protected String name; protected int level; / / add menu public void the add (MenuComponent MenuComponent) {throw new UnsupportedOperationException (); } / / remove menu public void remove (MenuComponent MenuComponent) {throw new UnsupportedOperationException (); } / / access to specified submenu public MenuComponent getChild (int I) {throw new UnsupportedOperationException (); } public String getName() {return name; } / / print method public void print () {throw new UnsupportedOperationException (); }}

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

package com.zhuang.combination; import java.util.ArrayList; import java.util.List; /** * @ClassName Menu * @Description * @Date 2021/3/24 17:05 * @Created by Dell */ public class Menu extends MenuComponent { private List<MenuComponent> menuComponentList; public Menu(String name, int level) { this.name = name; this.level = level; 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() { for (int i = 0; i < level; i++) { System.out.print("--"); } System.out.println(name); for (MenuComponent menuComponent : menuComponentList) { menuComponent.print(); }}}

MenuItem is a MenuItem and cannot have submenus, so adding menus, removing menus, and getting submenus are not possible.

package com.zhuang.combination; /** * @ClassName MenuItem * @Description * @Date 2021/3/24 17:10 * @Created by Dell */ public class MenuItem  extends MenuComponent { public MenuItem(String name, int level) { this.name = name; this.level = level; } @Override public void print() { for (int i = 0; i < level; i++) { System.out.print("--"); } System.out.println(name); }}

When using composite pattern, according to the definition form of abstract component class, we can divide composite pattern into two forms: transparent composite pattern and safe composite pattern.

  • Transparent combination mode

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

    The disadvantage of the transparent composition pattern is that it is not secure, because the leaf object and the container object are different in nature. The leaf object cannot have the next level of objects, that is, it cannot contain member objects, so it makes no sense to provide methods such as add(), remove(), etc., which will not go wrong at compile time. But at run time, calling these methods can be an error (if no corresponding error handling code is provided)

  • Safe combination mode

    In the security composition pattern, no methods for managing member objects are declared in the abstract component role; instead, these methods are declared and implemented in the branch node Menu class. The disadvantage 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 container components are not defined in the abstract component class, so clients cannot program completely against abstractions and must treat leaf and container components differently.

16.3 Application scenarios of composite patterns

  1. Where there is a need to represent a hierarchy of whole and part objects.
  2. Where the differences between a composite object and a single object are required to be hidden from the user and all objects in the composite structure can be used by the user with a uniform interface.

Write in the last

  • If my article is useful to you, please click 👍, thank you!
  • Let me know in the comments section if you have any questions! 💪