使用Composite Pattern 为您的所有对象提供一个通用接口。
一个接口或抽象超类,组件,代表所有可能有关系的对象。一个子类 Leaf 没有任何子类。 (可能还有其他非复合类叶子类。)另一个子类,Composite,包含许多对象,通常是任何类型的组件。这允许 Composite 包含其他 Composites 或其他非复合材料,例如 Leaf。
我在这里创建的组件超类是ComponentObject。这里,所有ComponentObjects都有一个父级CategoryObject,下面介绍。
组件对象
public abstract class ComponentObject
{
private CategoryObject myParent;
protected ComponentObject(CategoryObject parent)
{
myParent = parent;
}
public CategoryObject getParent()
{
return myParent;
}
public abstract int getNumChildren();
}
它有两个具体的子类,NonCategoryObject,不能包含子对象的 Leaf,和 CategoryObject,封装子对象列表的 Composite,可以是其他 CategoryObjects 或 NonCategoryObjects。
NonCategoryObject
public class NonCategoryObject extends ComponentObject
{
public NonCategoryObject(CategoryObject parent)
{
super(parent);
}
@Override
public int getNumChildren()
{
return 0;
}
}
类别对象
public class CategoryObject extends ComponentObject
{
private ArrayList<ComponentObject> myChildren;
public CategoryObject(CategoryObject parent)
{
super(parent);
myChildren = new ArrayList<ComponentObject>();
}
public void addChild(ComponentObject child)
{
myChildren.add(child);
}
public ComponentObject getChild(int index)
{
return myChildren.get(index);
}
public int getNumDirectChildren()
{
return myChildren.size();
}
@Override
public int getNumChildren()
{
int numChildren = 0;
for (ComponentObject child : myChildren)
{
// One for the child itself, plus add any of the child's children.
numChildren += 1 + child.getNumChildren();
}
return numChildren;
}
}
“getNumChildren”方法对于通过复合模式查找子节点的数量很重要。
设置数据
您有一个 ArrayList 的组件,每个组件都知道它们的父级,但不知道它们的子级是谁:
public static void main(String[] args)
{
// Create a tree structure, parent information only.
CategoryObject root = new CategoryObject(null);
CategoryObject categoryOne = new CategoryObject(root);
CategoryObject categoryTwo = new CategoryObject(root);
CategoryObject categoryThree = new CategoryObject(root);
CategoryObject categoryOneOne = new CategoryObject(categoryOne);
CategoryObject categoryOneTwo = new CategoryObject(categoryOne);
CategoryObject categoryOneThree = new CategoryObject(categoryOne);
NonCategoryObject leafOneFour = new NonCategoryObject(categoryOne);
NonCategoryObject leafOneOneOne = new NonCategoryObject(categoryOneOne);
NonCategoryObject leafOneOneTwo = new NonCategoryObject(categoryOneTwo);
NonCategoryObject leafOneTwoOne = new NonCategoryObject(categoryOneTwo);
NonCategoryObject leafOneThreeOne = new NonCategoryObject(categoryOneThree);
NonCategoryObject leafTwoOne = new NonCategoryObject(categoryTwo);
NonCategoryObject leafThreeOne = new NonCategoryObject(categoryThree);
// We're given the ArrayList
ArrayList<ComponentObject> components = new ArrayList<ComponentObject>();
// The order doesn't matter.
components.addAll(Arrays.asList(leafOneFour, leafOneOneTwo, leafOneThreeOne,
categoryOne, categoryOneOne, categoryOneThree, root, leafThreeOne,
leafOneOneOne, categoryThree, leafOneTwoOne, leafTwoOne,
categoryTwo, categoryOneTwo));
通过遍历列表来确定子信息。我们还将找到根(假设只有一个无父组件)。
ComponentObject foundRoot = null;
for (ComponentObject c : components)
{
CategoryObject parent = c.getParent();
if (parent == null)
{
foundRoot = c;
}
else
{
parent.addChild(c);
}
}
现在所有的父母都知道他们的孩子是谁了。接下来,我们将调用 2 个不同的方法,每个方法都有自己的方法来确定孩子的数量:
// 2 methods to determine the number of children.
compositeMethod(foundRoot);
recursiveMethod(foundRoot);
}
方法
这里是方法。一是“复合”法,它利用复合模式来确定孩子的数量。它只是调用根的getNumChildren() 方法。
private static void compositeMethod(ComponentObject root)
{
int numChildren = root.getNumChildren();
System.out.println("Composite method: " + numChildren);
}
输出:
Composite method: 13
复合方法并不是完全递归的,因为即使它调用自身,它调用自身的对象也是不同的。它在对象的孩子上调用自己。
您感兴趣的递归方法在层次结构的每个级别调用自身:
private static void recursiveMethod(ComponentObject root)
{
int numChildren = findNumChildren(root);
System.out.println("Recursive method: " + numChildren);
}
// The actual recursive method.
private static int findNumChildren(ComponentObject root)
{
if (root instanceof CategoryObject)
{
CategoryObject parent = (CategoryObject) root;
int numChildren = 0;
for (int i = 0; i < parent.getNumDirectChildren(); i++)
{
ComponentObject child = parent.getChild(i);
// One for the child itself, plus its children.
numChildren += 1 + findNumChildren(child);
}
return numChildren;
}
// Base case: NonCategoryObjects have no children.
return 0;
}
输出:
Recursive method: 13