设计模式

您所在的位置:网站首页 java组合模式实例 设计模式

设计模式

2023-04-22 19:36| 来源: 网络整理| 查看: 265

组合模式的定义&特点

组合(Composite Pattern)模式的定义:整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式,举个简单的例子,如下图所示:

image.png 电脑桌面为根节点,回收站、我的电脑、游戏文件夹为树叶节点,文件1、文件2、ppt文件、工作文件夹、王者荣耀为树叶节点。

先简单通过颜色进行区分,其实根节点和树枝节点本质上属于同一种数据类型,都为棕红色,都可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。组合模式中,会把树枝节点和叶子节点实现同一个接口,方便统一控制。

优点:

定义层次的关系上,又忽略了层次之间的差异,方便客户端对整个层次结构的控制。 新增、删除节点的时候,客户端无需修改代码,满足“开闭原则”;

缺点:

层级关系梳理复杂。 不容易限制类型,举个例子:游戏文件夹只能包含游戏类的文件,使用组合模式时,不能依赖类型系统进行约束,它们都来自于节点的抽象层,在这种情况下,必须通过在运行时进行类型检查,这样就变得比较复杂。 设计变得更加的抽象化。 组合模式的结构与实现 1. 组合模式的结构都有哪些角色组成?

答:组合模式包含以下3个主要角色。

(1)抽象构件(Component)角色 Interface:它作为树叶和树枝 共同实现的接口,定义共同的方法。

在透明式组合模式中 定义 了访问和管理树叶子类的方法; 在安全式的组合模式中 则 不定义 访问和管理树叶子类的方法,管理工作由树枝构件完成。 (2)树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

(3)树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件定义的方法。

2、组合模式有哪两种类型呢?

答:2种

(1) 透明方式 抽象构件接口声明了所有子类中的全部方法,客户端无须区别树叶对象和树枝对象。 树叶构件本来没有 Add()、Remove() 及 GetChild()方法,因为实现了抽象构建接口,被迫要实现它们,一般情况是抛出异常,或者空方法,这样会带来一些安全性问题。

为了更清晰的理解,我们举个栗子~上代码!

1、抽象构建类

/** * 抽象构件类 **/ public abstract class Component { public abstract void add(Component c); public abstract void remove(Component c); public abstract Component getChild(int i); public abstract ArrayList getChilds(); public abstract void touch(); public String name; public Component(String name) { this.name = name; } // 公有操作 public void getName() { System.out.println(this.name); } } 复制代码

2、树枝构件类

/** * 树枝构件类 **/ public class Composite extends Component { public Composite(String name) { super(name); this.children = new ArrayList(); } private ArrayList children = new ArrayList(); public void add(Component c) { children.add(c); } public void remove(Component c) { children.remove(c); } public Component getChild(int i) { return children.get(i); } public ArrayList getChilds() { return children; } public void touch() { for (Object obj : children) { ((Component) obj).touch(); } } } 复制代码

3、叶子构建类

/** * 叶子构件 **/ public class Leaf extends Component { Leaf(String name) { super(name); } public void add(Component c) { throw new UnsupportedOperationException("操作不支持"); } public void remove(Component c) { throw new UnsupportedOperationException("操作不支持"); } public Component getChild(int i) { throw new UnsupportedOperationException("操作不支持"); } @Override public ArrayList getChilds() { throw new UnsupportedOperationException("操作不支持"); } public void touch() { System.out.println("执行:" + name + " 业务逻辑!"); } } 复制代码

3、测试

/** * 测试 **/ public class CompositePattern { public static void main(String[] args) { Composite root = new Composite("树根节点"); Composite c0 = new Composite("树枝节点A"); Composite c1 = new Composite("树枝节点B"); Component leaf1 = new Leaf("树叶1"); Component leaf2 = new Leaf("树叶2"); Component leaf3 = new Leaf("树叶3"); Component leaf4 = new Leaf("树叶4"); root.add(c0); root.add(c1); c0.add(leaf1); c1.add(leaf2); c1.add(leaf3); c1.add(leaf4); root.touch(); recurrenceTree(root); } private static void recurrenceTree(Composite root) { ArrayList children = root.getChilds(); for (Component c : children) { if (c instanceof Leaf) { System.out.print("\t"); c.getName(); } else { c.getName(); // 递归 recurrenceTree((Composite) c); } } } } 复制代码

执行结果如下:

image.png

(2) 安全方式 只有树枝构件中实现了管理子构件的方法,抽象构件不再声明对子对象的管理方法、树叶构件不再实现管理子类的方方,避免了透明方式中的安全性的问题。 测试类在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。

为了便于理解,我们在透明模式的基础上升级为安全模式,大家一比对就清楚了。

1、抽象构建类-去掉了管理子类的方法

/** * 抽象构件类、节点类 **/ public abstract class Component { public abstract void touch(); public String name; public Component(String name) { this.name = name; } // 公有操作 public void getName() { System.out.println(this.name); } } 复制代码

2、叶子构建类-不再实现管理子类的方法。

/** * 叶子构件 **/ public class Leaf extends Component { Leaf(String name) { super(name); } public void touch() { System.out.println("执行:" + name + " 业务逻辑!"); } } 复制代码 说了半天,组合模式的实际应用场景有没有例子呢??

答:有 比如:计算公司预算情况,需要按照每个部门来进行分类、汇总,一个大公司下面有产品部门、研发部门等,产品部门可能分为一级、二级、三级等。

和之前的demo不太一样的地方,这里并没有定义为abstract,而是interface接口(原理一样~)上代码~ 1、抽象构建类

/** * 抽象构建 **/ public interface Jiesuan { //计算公司预算 float calculMoney(); //获取部门人员具体预算 void getMsg(); } 复制代码

2、树枝构建类

/** * 树枝构建 **/ public class JiesuanComposite implements Jiesuan { private String name; private ArrayList orderJiesuan = new ArrayList(); public JiesuanComposite() { } public JiesuanComposite(String name) { this.name = name; } public void add(Jiesuan c) { orderJiesuan.add(c); } public void remove(Jiesuan c) { orderJiesuan.remove(c); } public Jiesuan getChild(int i) { return orderJiesuan.get(i); } public float calculMoney() { float s = 0; for (Object obj : orderJiesuan) { s += ((Jiesuan) obj).calculMoney(); } return s; } @Override public void getMsg() { System.out.println(name+"预算"); for (Object obj : orderJiesuan) { ((Jiesuan) obj).getMsg(); } } } 复制代码

3、叶子构建类

/** *叶子构建 **/ public class Yusuan implements Jiesuan { private String name; //名字 private Float peoplePrice; //预算 //默认构造器 public Yusuan() { } //自定义构造器 public Yusuan(String name, Float peoplePrice) { this.name = name; this.peoplePrice = peoplePrice; } @Override public float calculMoney() { return peoplePrice; } @Override public void getMsg() { System.out.println(name+":"+peoplePrice); } } 复制代码

4、测试

/** * 测试 **/ public class JiesuanPattern { public static void main(String[] args) { Float s ; Yusuan yusuan; JiesuanComposite gongsi = new JiesuanComposite("公司"); JiesuanComposite cpLevel1 =new JiesuanComposite("产品一级部门"); JiesuanComposite yfLevel1 = new JiesuanComposite("研发一级部门"); JiesuanComposite yfLevel2A = new JiesuanComposite("研发二级部门A"); JiesuanComposite yfLevel2B = new JiesuanComposite("研发二级部门B"); yusuan = new Yusuan("产品一级部门-孙三", 1117f); cpLevel1.add(yusuan); yusuan = new Yusuan("研发一级部门-孙四", 2222f); yfLevel1.add(yusuan); yusuan = new Yusuan("研发二级部门A-李莉", 1211f); yfLevel2A.add(yusuan); yusuan = new Yusuan("研发二级部门A-李磊", 1211f); yfLevel2A.add(yusuan); yusuan = new Yusuan("研发二级部门B-陈好", 2231f); yfLevel2B.add(yusuan); yfLevel1.add(yfLevel2A); yfLevel1.add(yfLevel2B); gongsi.add(cpLevel1); gongsi.add(yfLevel1); gongsi.getMsg(); s = gongsi.calculMoney(); System.out.println("公司总预算:" + s + "元"); } } 复制代码

结果打印如下:

image.png



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3