「叶子构件」:Group,叶子构件不没有子节点了,所以不需要添加、删除之类的方法
public class Group extends OrganizationComponent { public Group(String name) { super(name); } @Override protected void print() { System.out.println(getName()); } @Override public String getName() { return super.getName(); } }「测试类」:Client
public class Client { @Test public void test01(){ OrganizationComponent company = new Company("阿里巴巴"); OrganizationComponent department1 = new Department("市场部"); OrganizationComponent department2 = new Department("技术部"); OrganizationComponent group1 = new Group("市场一组"); OrganizationComponent group2 = new Group("市场二组"); OrganizationComponent group3 = new Group("技术一组"); OrganizationComponent group4 = new Group("技术二组"); //添加部门 company.add(department1); company.add(department2); //添加小组 department1.add(group1); department1.add(group2); department2.add(group3); department2.add(group4); //打印结果 company.print(); } }「运行结果」
=======阿里巴巴======= =======市场部======= 市场一组 市场二组 =======技术部======= 技术一组 技术二组 在 HashMap 中的应用在 Java(jdk 1.8为例) 的集合类 HashMap 中,抽象构件是 Map,容器构件是 HashMap,叶子构件是 Node
进入源码可以看见,在 Map 中定义了许多公共方法
HashMap 实现了 Map,并对一些方法重写,而且 HashMap 中有一个静态内部类 Node,它就充当了叶子构件的角色,Node 中去除了 put、putAll 等方法,下面也没有子结点了
使用:
@Test public void test02(){ Map<String, String> map = new HashMap<>(); map.put("k1", "v1"); map.put("k2", "v2"); System.out.println(map); }当我们 put 一个键值对的时候,在 HashMap 内部会调用 putVal 方法,将键值对封装为 Node。
总结1、简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子的问题。
2、具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系,客户端不用做出任何改动。
3、方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构。
4、需要遍历组织机构,或者处理的对象具有树形结构时,非常适合使用组合模式。
5、要求较高的抽象性。如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式。
四、装饰者模式(Decorator) 基本装饰者模式属于结构型模式,它可以动态的将新功能附加到对象上,同时又不改变其结构。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(OCP)。
模式结构装饰者和被装饰者有相同的超类型,因为装饰者和被装饰者必须是一样的类型,利用继承是为了达到类型的匹配,而不是利用继承获取行为
Component:装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为
ConcreteComponent:定义具体对象,即被装饰者
Decorator:抽象装饰者,继承自 Component,从外类来扩展 ConcreteComponent。对于 ConcreteComponent来说,不需要知道Decorator的存在,Decorator 是一个接口或抽象类
ConcreteDecorator:具体装饰者,用于扩展 ConcreteComponent
举例说明在咖啡店客人想点一杯加两份糖一份牛奶的摩卡咖啡,各个商品的价格如下,我们需要根据用户点的咖啡、加的配料,动态的计算价格
商品 价格拿铁咖啡(LatteCoffee) 4.5
摩卡咖啡(MochaCoffe) 5.5
糖(Sugar) 1.0
牛奶(Milk) 2.0
「实体类」 Coffee
public abstract class Coffee{ public String des = "咖啡"; //描述 private float price = 0.0f; //价格 protected abstract float cost(); //计算费用 //省略getter setter方法 }「被装饰者」LatteCoffee
public class LatteCoffee extends Coffee{ public LatteCoffee() { setDes("拿铁咖啡"); setPrice(4.5f); } @Override protected float cost() { return getPrice(); } }