Java design pattern - composite pattern

Combination mode

Business requirements

  • The school displays the structure of colleges and departments. A school has multiple colleges and a college has multiple departments;
  • Traditional thinking, the Department inherits the college, and the college inherits the school;

problem analysis

  • The college is regarded as a subclass of the school, and the Department is a subclass of the college. In fact, it is hierarchical based on the size of the organization
  • In fact, our requirement is that a school has multiple colleges and a college has multiple departments; The traditional scheme can not well realize management operations, such as adding, deleting and traversing colleges and departments
  • Solution: regard schools, colleges and departments as organizational structures. There is no inheritance relationship between them, but a tree structure, which can better realize management operation

Basic introduction

  • Combination mode, also known as partial whole mode, creates a tree structure of object groups, combines objects into a tree structure, and represents the hierarchical relationship between whole and part
  • Combination mode is a tree structure to combine objects, which is used to represent part and whole levels
  • This type of design pattern belongs to structural pattern
  • The combination mode is that users have consistent access to single objects and combined objects, that is, the combination allows customers to deal with individual objects and combined objects in a consistent way

Schematic description

  • 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. It can make abstract classes or interfaces
  • Leaf: represents a leaf node in a combination. A leaf node has no child nodes and acts as a managed person
  • Composite: non leaf node, used to store sub components and implement related operations of sub components in the Component interface, such as adding and deleting; Act as manager

    Problems solved
  • Composite mode solves such problems. When the object we want to deal with 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


code implementation


Organization parent class, which can be general class, abstract class and interface

The method implemented by default determines whether the parent method can be used according to whether the lower node is a leaf node

@Data
public abstract class OrganizationComponent {
    private String name;
    private String des;
    public OrganizationComponent(String name, String des) {
        super();
        this.name = name;
        this.des = des;
    }
    protected void add(OrganizationComponent organizationComponent) {
        // Default implementation
        throw new UnsupportedOperationException();
    }
    protected void remove(OrganizationComponent organizationComponent) {
        // Default implementation
        throw new UnsupportedOperationException();
    }
    // Subclasses need to be implemented
    protected abstract void print();
}

Define university classes

public class University extends OrganizationComponent{
    List<OrganizationComponent> list = new ArrayList<>();
    public University(String name, String des) {
        super(name, des);
    }
    @Override
    protected void add(OrganizationComponent organizationComponent) {
        list.add(organizationComponent);
    }
    @Override
    protected void remove(OrganizationComponent organizationComponent) {
        list.remove(organizationComponent);
    }
    // Output the colleges contained in the current University
    @Override
    protected void print() {
        System.out.println("============="+getName()+"===============");
        for (OrganizationComponent o : list) {
            o.print();
        }
    }
}

Define college class

public class College extends OrganizationComponent{
    List<OrganizationComponent> list = new ArrayList<>();
    public College(String name, String des) {
        super(name, des);
    }
    @Override
    protected void add(OrganizationComponent organizationComponent) {
        list.add(organizationComponent);
    }
    @Override
    protected void remove(OrganizationComponent organizationComponent) {
        list.remove(organizationComponent);
    }
    // Output the colleges contained in the current College
    @Override
    protected void print() {
        System.out.println("============="+getName()+"===============");
        for (OrganizationComponent o : list) {
            o.print();
        }
    }
}

Define specific system

public class Department extends OrganizationComponent{
    public Department(String name, String des) {
        super(name, des);
    }
    // The leaf node does not have add / delete, and add and remove are no longer rewritten
    @Override
    protected void print() {
        System.out.println(getName());
    }
}

client

public class Client {
    public static void main(String[] args) {
        // Create a school
        OrganizationComponent university = new University("Tsinghua University", "Famous Chinese Schools");
        // 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 system
        computerCollege.add(new Department("software engineering", "Software engineering is really good"));
        computerCollege.add(new Department("Network engineering", "Network engineering is also good"));
        computerCollege.add(new Department("Computer science and technology", "Computer science and technology can also"));

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

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

        // If you need to view which level, you can output it directly
        university.print();
        System.out.println("##################Split line####################");
        computerCollege.print();
    }
}

JDK source code analysis - HashMap

Demo

public class Composite {
    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        // Save to leaf node
        hashMap.put(0, "Water Margin");
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Journey to the West");
        map.put(2, "The Dream of Red Mansion");
        // Storage node
        hashMap.putAll(map);
        System.out.println(hashMap);
    }
}

Source code fragment

public interface Map<K, V> {
...
    V put(K var1, V var2);
...
    void putAll(Map<? extends K, ? extends V> var1);

public abstract class AbstractMap<K,V> implements Map<K,V> {
	...
	public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    ...
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }
}
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
	...
	public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    ...
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
	...
        return null;
    }
    ...
    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }
}

explain

  • Map is an abstract build (similar to the previous Component)
  • HashMap is a Composite that implements / inherits the relevant method put/putAll
  • Node is a static internal class of HashMap, similar to Leaf node, without put/putAll

Pay attention to implementation and details

  • Simplify the client operation. The client only needs to face consistent objects without considering the whole part or leaf node
  • It has strong scalability. When we want to change the composite object, we only need to adjust the internal hierarchical relationship, and the client does not need to make any changes
  • It is convenient to create a complex hierarchy. The client does not care about the composition details in the composition. It is easy to add nodes or leaves to create a complex tree structure
  • When you need to traverse the organization, or when the object you are dealing with has an attribute structure, it is very suitable to use the composite pattern
  • It requires high abstraction. If there are many differences between nodes and leaves, such as different methods and attributes, it is not suitable to use composite mode

Keywords: Java Design Pattern Algorithm

Added by schoi on Fri, 14 Jan 2022 06:33:44 +0200