一、上下文及问题
将对象组合成树型结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
二、常见场景
1、如果你想表示对象的部分-整体层次结构,可以选用组合模式,把整体和部分的操作统一起来,是的层次结构实现更简单,从外部来使用这个层次结构也容易。
2、如果你希望统一滴使用组合结构中的所有对象,可以选用组合模式,这正是组合模式提供的主要功能。
比如管理品类,人员组织结构。
三、解决方法
1、安全型的组合模式
父类只定义公共的方法,客户端得区分哪些是部分哪些是整体,各自的操作方法有不同,之所以说是安全,是因为,没有把特殊子类不支持的方法放到公用类里头,不会引发操作不支持。
2、透明的组合模式
父类在公共方法里头,定义了管理方法,对客户端来说是透明的,它不需要区分谁是整体谁是部分,但是可能引用操作不安全,比如调用的方法,特殊子类并不支持。
四、抽象模型
五、代码实例
1、安全型
抽象类
public abstract class BranchComponent {
public String getName() {
throw new UnsupportedOperationException();
}
public String getDiscription() {
throw new UnsupportedOperationException();
}
public void display() {
throw new UnsupportedOperationException();
}
}
子类1
public class BranchLeaf extends BranchComponent {
private String name;
private String discription;
public BranchLeaf(String name, String discription) {
this.name = name;
this.discription = discription;
}
public void display() {
System.out.printf("\t%s: %s\n", name, discription);
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
子类2
public class BranchComposite extends BranchComponent {
private String name;
private String discription;
private List<BranchComponent> childrenBranch;
public BranchComposite(String name, String discription) {
this.name = name;
this.discription = discription;
childrenBranch = new ArrayList<BranchComponent>();
}
public void display() {
System.out.printf("%s: %s\n", name, discription);
for (BranchComponent child : childrenBranch) {
child.display();
}
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
public void add(BranchComponent child) {
childrenBranch.add(child);
}
public void remove(BranchComponent child) {
childrenBranch.remove(child);
}
public BranchComponent getChild(int index) {
return childrenBranch.get(index);
}
}
客户端
public class TestDrive {
public static void main(String[] args) {
BranchComposite china = new BranchComposite("CN", "China Branch");
BranchComposite shanghai = new BranchComposite("Sh", "Shanghai Branch");
BranchLeaf huangpu = new BranchLeaf("Hp", "Huangpu Branch");
BranchLeaf yangpu = new BranchLeaf("Yp", "Yangpu Branch");
BranchLeaf pudong = new BranchLeaf("Pd", "Pudong Branch");
BranchComposite beijing = new BranchComposite("Bj", "Beijing Branch");
BranchLeaf dongcheng = new BranchLeaf("Dc", "Dongcheng Branch");
BranchLeaf xicheng = new BranchLeaf("Xc", "Xicheng Branch");
BranchLeaf haidian = new BranchLeaf("Hd", "Haidian Branch");
shanghai.add(huangpu);
shanghai.add(yangpu);
shanghai.add(pudong);
beijing.add(dongcheng);
beijing.add(xicheng);
beijing.add(haidian);
china.add(shanghai);
china.add(beijing);
System.out.println("Displaying the head bank information");
display(china);
System.out.println("\nDisplaying Shanghai bank branch information");
display(shanghai);
System.out.println("\nDisplaying Pudong bank branch information in Shanghai");
display(pudong);
}
private static void display(BranchComponent branch) {
branch.display();
}
}
2、透明型
抽象类
public abstract class BranchComponent {
public String getName() {
throw new UnsupportedOperationException();
}
public String getDiscription() {
throw new UnsupportedOperationException();
}
public void display() {
throw new UnsupportedOperationException();
}
public void add(BranchComponent child) {
throw new UnsupportedOperationException();
}
public void remove(BranchComponent child) {
throw new UnsupportedOperationException();
}
public BranchComponent getChild(int index) {
throw new UnsupportedOperationException();
}
}
子类1
public class BranchLeaf extends BranchComponent {
private String name;
private String discription;
public BranchLeaf(String name, String discription) {
this.name = name;
this.discription = discription;
}
public void display() {
System.out.printf("\t%s: %s\n", name, discription);
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
}
子类2
public class BranchComposite extends BranchComponent {
private String name;
private String discription;
private List<BranchComponent> childrenBranch;
public BranchComposite(String name, String discription) {
this.name = name;
this.discription = discription;
childrenBranch = new ArrayList<BranchComponent>();
}
public void display() {
System.out.printf("%s: %s\n", name, discription);
for (BranchComponent child : childrenBranch) {
child.display();
}
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
public void add(BranchComponent child) {
childrenBranch.add(child);
}
public void remove(BranchComponent child) {
childrenBranch.remove(child);
}
public BranchComponent getChild(int index) {
return childrenBranch.get(index);
}
}
客户端
public class TestDrive {
public static void main(String[] args) {
BranchComposite china = new BranchComposite("CN", "China Branch");
BranchComposite shanghai = new BranchComposite("Sh", "Shanghai Branch");
BranchLeaf huangpu = new BranchLeaf("Hp", "Huangpu Branch");
BranchLeaf yangpu = new BranchLeaf("Yp", "Yangpu Branch");
BranchLeaf pudong = new BranchLeaf("Pd", "Pudong Branch");
BranchComposite beijing = new BranchComposite("Bj", "Beijing Branch");
BranchLeaf dongcheng = new BranchLeaf("Dc", "Dongcheng Branch");
BranchLeaf xicheng = new BranchLeaf("Xc", "Xicheng Branch");
BranchLeaf haidian = new BranchLeaf("Hd", "Haidian Branch");
shanghai.add(huangpu);
shanghai.add(yangpu);
shanghai.add(pudong);
beijing.add(dongcheng);
beijing.add(xicheng);
beijing.add(haidian);
china.add(shanghai);
china.add(beijing);
System.out.println("Displaying the head bank information");
display(china);
System.out.println("\nDisplaying Shanghai bank branch information");
display(shanghai);
System.out.println("\nDisplaying Pudong bank branch information in Shanghai");
display(pudong);
}
private static void display(BranchComponent branch) {
branch.display();
}
}
3、组织结构实例
Tree
public class Tree<T extends TreeObject> {
private TreeNode<T> root;
private Map<Integer,TreeNode<T>> treeMap = new HashMap<Integer, TreeNode<T>>();
public Tree(T rootData){
root = new TreeNode<T>();
root.setData(rootData);
}
public Tree(List<T> lists){
constructFromList(lists);
}
public void constructFromList(List<T> lists){
for(T obj:lists){
if(treeMap.containsKey(obj.getId()) == false){
treeMap.put(obj.getId(),new TreeNode<T>(obj));
}
}
for(T obj:lists){
TreeNode<T> currentNode = treeMap.get(obj.getId());
TreeNode<T> parent = treeMap.get(obj.getParentId());
if(obj.getParentId() == null || obj.getParentId() == 0){
this.root = currentNode;
}else{
//add to parent
if(currentNode.getParent() == null){
currentNode.setParent(parent);
}
parent.addChild(currentNode);
}
}
System.out.println(ReflectTool.getObjectSize(treeMap, SizeEnum.M));
}
public TreeNode<T> findById(Integer id){
TreeNode<T> treeNode = treeMap.get(id);
return treeNode;
}
//递归获取下属实例
public void findNodeLeaves(TreeNode<T> node,List<T> collects){
if(node == null)
return;
if(node.getData().getIsEmployee()){
collects.add(node.getData());
// System.out.println(node.getData());
}else{
System.out.println(node.getData());
}
if(node.getChildren().size() == 0)
return;
for(TreeNode<T> cld : node.getChildren()){
findNodeLeaves(cld,collects);
}
}
}
TreeNode
public class TreeNode<T> {
private T data;
private TreeNode<T> parent;
private Set<TreeNode<T>> children = new HashSet<TreeNode<T>>();
public TreeNode() {
}
public TreeNode(T data) {
this.data = data;
}
public void addChild(TreeNode<T> child){
children.add(child);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public TreeNode<T> getParent() {
return parent;
}
public void setParent(TreeNode<T> parent) {
this.parent = parent;
}
public Set<TreeNode<T>> getChildren() {
return children;
}
}
客户端
public class TreeNodeTest {
@Test
public void testTree() throws IOException {
URL url = Resources.getResource("Depts.json");
String text = Resources.toString(url, Charsets.UTF_8);
List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
data = JsonTool.parseToObject(text,data.getClass());
List<OrgEmployeeInfo> infos = new ArrayList<OrgEmployeeInfo>();
for(Map map:data){
String idStr = (String) map.get("id");
Integer id = Integer.valueOf(idStr.substring(1));
String parIdStr = (String) map.get("parentId");
Integer parentId = Integer.valueOf(parIdStr.substring(1));
String name = (String)map.get("name");
OrgEmployeeInfo info = new OrgEmployeeInfo(id,name,parentId);
Object orgCategory = map.get("orgCategory");
if(orgCategory == null){
info.setIsEmployee(true);
}
infos.add(info);
}
// List<OrgEmployeeInfo> infos = new ArrayList<OrgEmployeeInfo>();
// infos.add(new OrgEmployeeInfo(1,"boss",null));
//
// infos.add(new OrgEmployeeInfo(2,"dep1",1));
// infos.add(new OrgEmployeeInfo(3,"dep2",1));
// infos.add(new OrgEmployeeInfo(4,"dep3",1));
//
// infos.add(new OrgEmployeeInfo(5,"subdep1-1",2));
// infos.add(new OrgEmployeeInfo(6,"subdep1-2",2));
// infos.add(new OrgEmployeeInfo(7,"subdep1-3",2));
//
// infos.add(new OrgEmployeeInfo(9665,"subdep3-1",4));
Tree<OrgEmployeeInfo> tree = new Tree<OrgEmployeeInfo>(infos);
TreeNode<OrgEmployeeInfo> node = tree.findById(674);
List<OrgEmployeeInfo> childs = new ArrayList<OrgEmployeeInfo>();
tree.findNodeLeaves(node,childs);
for(OrgEmployeeInfo cld:childs){
System.out.println(cld.toString());
}
System.out.println(ReflectTool.getObjectSize(infos, SizeEnum.M));
}
}