设计模式-组合模式(10)
定义
组合(Composite Pattern)模式也叫合成模式,用来描述部分与整体的关系。英文原话是:Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual object and compositions of objects uniformly.意思是:将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
组合模式分为三个角色:
1.抽象构件(Component)角色:该角色定义参加组合的对象的共有方法和属性,规范一些默认的行为接口。
2.叶子构件(Leaf)角色:该角色是叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为。
3.树枝构件(Composite)角色:该角色代表参加组合的、其下有分支的树枝对象,它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法,如add()、remove()等。
//定义抽象构建接口 public interface Component { public void operation(); } /** * 树枝构件 */ public class Composite implements Component { //构建容器 private ArrayList<Component> componentList = new ArrayList<Component>(); //添加构件 public void add(Component component){ this.componentList.add(component); } //删除构件 public void remove(Component component){ this.componentList.remove(component); } //获取子构件 public ArrayList<Component> getChild(){ return this.componentList; } @Override public void operation() { //省略业务逻辑代码 System.out.println(this.toString()+"树枝构建业务"); } } /** * 叶子构件 */ public class Leaf implements Component { @Override public void operation() { //省略业务逻辑代码 System.out.println(this.toString()+"叶子构建业务"); } } /** * 调用 */ public class Client { public static void main(String[] args) { //创建一个跟节点 Composite root = new Composite(); root.operation(); //创建树枝节点 Composite branch = new Composite(); //创建叶子节点 Leaf leaf = new Leaf(); //创建树形结构 root.add(branch); branch.add(leaf); display(root); } //遍历树(递归) public static void display(Composite root){ for (Component c:root.getChild()) { if (c instanceof Leaf) { //如果节点类型是叶子节点 c.operation(); }else { //树枝节点 c.operation(); display((Composite)c); } } } }
组合模式优点
- 高层模块调用简单。一颗树形机构的所有节点都是Component,局部和整体对于调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
- 节点自由增加。使用组合模式后,如果想增加树枝节点、树叶节点,只需找到其父节点即可。
组合模式缺点
- 不易控制树枝构件的类型。
- 不易使用继承的方法来增加新的行为。
使用场景
- 需要描述对象的部分和整体之间的等级结构关系,如树形菜单、文件和文件夹管理等。
- 需要客户端忽略个体构件和组合构件的区别,平等的对待所有的构建。
组合模式也是应用广泛的一种设计模式。例如,java基础类库的swing部分就是大量使用了组合模式,其中大部分控件都是JComponent的子类,同时其add()方法又可向界面添加JComponent类型的控件,从而使得使用者能够以统一的方式操作各种控件。
/** * 抽象接口 */ public interface Company { //获取信息 public String getInfo(); } /** * 树枝节点类 */ public class ConcreteCompany implements Company{ //构件容器 private ArrayList<Company> companyList = new ArrayList<Company>(); private String name; private String sex; private String position; private int salary; public ConcreteCompany(String name,String sex, String position, int salary) { this.name = name; this.sex = sex; this.position = position; this.salary = salary; } //添加构件 public void add(Company company){ this.companyList.add(company); } //删除构件 public void remove(Company company){ this.companyList.remove(company); } public ArrayList<Company> getChild(){ return this.companyList; } //获取子构件 @Override public String getInfo() { String info = ""; info = "名称:"+this.name; info+="\t性别"+this.sex; info+="\t职位"+this.position; info+="\t薪水"+this.salary; return info; } } /** * 叶子节点类 */ public class Employee implements Company{ private String name; private String sex; private String position; private int salary; public Employee(String name,String sex, String position, int salary) { this.name = name; this.sex = sex; this.position = position; this.salary = salary; } @Override public String getInfo() { String info = ""; info = "名称:"+this.name; info+="\t性别"+this.sex; info+="\t职位"+this.position; info+="\t薪水"+this.salary; return info; } } //调用 public class DemoClient { public static void main(String[] args) { //CEO ConcreteCompany root = new ConcreteCompany("李彦宏", "男", "CEO", 1000000); //部门经理 ConcreteCompany developDep = new ConcreteCompany("郑亮", "男", "研发部经理", 9999999); ConcreteCompany salesDep = new ConcreteCompany("逍遥", "男", "销售部经理", 8888888); ConcreteCompany financeDep = new ConcreteCompany("小颖", "女", "财务不经理", 6666666); //部门员工 Employee e1 = new Employee("程序甲", "男", "java开发工程师", 10000); Employee e2 = new Employee("素材乙", "女", "素材师", 8888); Employee e3 = new Employee("UI丙", "男", "UI设计师", 8888); Employee e4 = new Employee("销售员甲", "男", "销售员", 6666); Employee e5 = new Employee("销售员乙", "男", "销售员", 6666); Employee e6 = new Employee("会计甲", "男", "会计", 5000); //生成树 root.add(developDep); root.add(salesDep); root.add(financeDep); developDep.add(e1); developDep.add(e2); developDep.add(e3); salesDep.add(e4); salesDep.add(e5); financeDep.add(e6); //递归树 display(root); } //遍历树(递归) public static void display(ConcreteCompany root){ for (Company c:root.getChild()) { if (c instanceof Employee) { System.out.println(c.getInfo()); }else { //树枝节点 System.out.println("\n"+c.getInfo()); display((ConcreteCompany) c); } } } }
如果这篇文章对你有用,可以关注本人微信公众号获取更多ヽ(^ω^)ノ ~