组合设计模式

96 阅读3分钟

GoF原文

Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.

When we need to create a structure in a way that the objects in the structure has to be treated the same way, we can apply composite design pattern. 当我们需要以同样的方式来处理结构中的对象时,我们可以应用组合设计模式。

组合模式主要有以下应用场景。

(1)希望客户端可以忽略组合对象与单个对象的差异。 (2)对象层次具备整体和部分,呈树形结构。 在这里插入图片描述

1. Base Component/基组件——基组件是组件中所有对象的接口。它可以是一个接口,也可以是一个抽象类,具有所有对象的一些通用方法2. Leaf –组成组合的各个组件,实现了基组件的功能,彼此独立没有引用关系 3. Composite – 负责管理各个组件,控制组件的调用,所有组件的功能又被基组件约束着。

Base Component

public interface A1_Shape {
	public void draw(String fillColor);
}

Leaf

public class A2_Triangle implements A1_Shape {
	@Override
	public void draw(String fillColor) {
		System.out.println("Drawing Triangle with color "+fillColor);
	}
}
public class A3_Circle implements A1_Shape {
	@Override
	public void draw(String fillColor) {
		System.out.println("Drawing Circle with color "+fillColor);
	}
}

Composite

public class A4_Drawing implements A1_Shape{
	private List<A1_Shape> shapes = new ArrayList<A1_Shape>();
	@Override
	public void draw(String fillColor) {
		for(A1_Shape sh : shapes)
		{
			sh.draw(fillColor);
		}
	}
	public void add(A1_Shape s){
		this.shapes.add(s);
	}
	public void remove(A1_Shape s){
		shapes.remove(s);
	}
	public void clear(){
		System.out.println("Clearing all the shapes from drawing");
		this.shapes.clear();
	}
}

使用

		A1_Shape tri = new A2_Triangle();
		A1_Shape tri1 = new A2_Triangle();
		A1_Shape cir = new A3_Circle();
		
		A4_Drawing drawing = new A4_Drawing();
		drawing.add(tri1);
		drawing.add(tri1);
		drawing.add(cir);
		drawing.draw("Red");
		
		drawing.clear();
		
		drawing.add(tri);
		drawing.add(cir);
		drawing.draw("Green");

结果

Drawing Triangle with color Red
Drawing Triangle with color Red
Drawing Circle with color Red
Clearing all the shapes from drawing
Drawing Triangle with color Green
Drawing Circle with color Green

组合模式在JDK源码中的应用

首先来看一个非常熟悉的HashMap,它有一个putAll()方法。

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
...
    public void putAll(Map<? extends K, ? extends V> m) {
        putMapEntries(m, true);
    }
    public V remove(Object key) {
        Node<K,V> e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
            null : e.value;
    }
...
    final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            }
            else if (s > threshold)
                resize();
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }
...

我们看到putAll()方法传入的是Map对象,

Map就是一个 Base Component

而HashMap是一个Composite

HashMap中的Node节点就是leaf

说到 Composite 就会有规定的存储方式。HashMap中的存储使用一个静态内部类的数组Node<K,V>[],源码如下。

    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;
        }
    }

我们常用的ArrayList对象也有addAll()方法,其参数也是ArrayList的父类Collection

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

Collection<? extends E> 就是一个 Base Component

而ArrayList是一个Composite

存储方式 是Object[]。

那么 leaf 是什么?

没搞懂?????????????

组合对象和被组合对象都应该有统一的接口实现或者统一的抽象父类。