结构型模式的目的是通过组合类或对象产生更大结构,以适应更高层次的逻辑需求;
结构型模式共有7种:
■ 代理模式
■ 装饰模式
■ 适配器模式
■ 组合模式
■ 桥梁模式
■ 外观模式
■ 享元模式
一、组合模式简介
组合模式(Composite Pattern)也叫合成模式,用来描述部分与整体的关系;
将对象组合成树形结构以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性;
# 组合模式3个角色
■ 抽象构件(Component)角色:该角色定义参加组合对象的共有方法和属性,规范一些默认的行为接口;
■ 叶子构件(Leaf)角色:该角色是叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为;
■ 树枝构件(Composite)角色:该角色代表参加组合的、其下有分支的树枝对象;
它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法,如add()、remove()等;

image.png
/**
* 抽象构件
*/
public interface Component {
void operation();
}
/**
* 树枝构件
*/
public class Composite implements Component{
private List<Component> componentList = new ArrayList<>();
// 添加构件
public void add(Component component){
this.componentList.add(component);
}
// 删除构件
public void remove(Component component){
this.componentList.remove(component);
}
// 获取子构件
public List<Component> getChildList(){
return this.componentList;
}
// 业务逻辑代码
@Override
public void operation() {
System.out.println("树枝构件业务逻辑代码");
}
}
/**
* 叶子构件
*/
public class Leaf implements Component{
// 业务逻辑代码
@Override
public void operation() {
System.out.println("叶子构件业务逻辑代码");
}
}
/**
* 应用代码
*/
public class ClientDemo {
public static void main(String[] args){
// 创建一个根节点
Composite root = new Composite();
// 创建树枝节点
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.getChildList()){
// 叶子节点
if(c instanceof Leaf){
c.operation();
}else{
// 树枝节点
c.operation();
display((Composite)c);
}
}
}
}
# 控制台输出:
树枝构件业务逻辑代码
叶子构件业务逻辑代码
二、组合模式的优缺点
# 组合模式的优点
■ 高层模块调用简单;
一棵树形机构中的所有节点都是Component;
■ 节点自由增加;
使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可;
# 组合模式的缺点
■ 不易控制树枝构件的类型;
■ 不易使用继承的方法来增加新的行为;
三、组合模式的使用场景
■ 需要描述对象的部分和整体的等级结构,如树形菜单、文件和文件夹管理;
■ 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件;
、组合模式的实例
# 使用组合模式实现公司各部门层次关系;

image.png
/**
* 抽象接口
*/
public interface Company {
// 获取信息
String getInfo();
}
import java.util.ArrayList;
import java.util.List;
/**
* 树枝节点
*/
public class ConcreteCompany implements Company{
private List<Company> companyList = new ArrayList<>();
// 姓名
private String name;
// 职位
private String position;
// 薪水
private int salary;
public ConcreteCompany(String name, String position, int salary) {
this.name = name;
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 List<Company> getChild(){
return companyList;
}
@Override
public String getInfo() {
return "公司{" +
" 姓名 ='" + name + '\'' +
", 职位 ='" + position + '\'' +
", 薪水 ='" + salary + '\'' +
'}';
}
}
/**
* 叶子节点
*/
public class Employee implements Company{
// 姓名
private String name;
// 职位
private String position;
// 薪水
private int salary;
public Employee(String name, String position, int salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
@Override
public String getInfo() {
return "公司{" +
" 姓名 ='" + name + '\'' +
", 职位 ='" + position + '\'' +
", 薪水 ='" + salary + '\'' +
'}';
}
}
/**
* 应用代码
*/
public class ClientDemo {
public static void main(String[] args){
ConcreteCompany root = new ConcreteCompany("张三","CEO",100000);
ConcreteCompany developDep = new ConcreteCompany("李四","研发部经理",12000);
ConcreteCompany salesDep = new ConcreteCompany("王五","销售部经理",15000);
ConcreteCompany financeDep = new ConcreteCompany("马六","财务部经理",10000);
Employee e1 = new Employee("A","研发部",1000);
Employee e2 = new Employee("B","研发部",1100);
Employee e3 = new Employee("C","研发部",1200);
Employee e4 = new Employee("D","研发部",1300);
Employee e5 = new Employee("E","研发部",1400);
Employee e6 = new Employee("F","销售部",1500);
Employee e7 = new Employee("G","销售部",1600);
Employee e8 = new Employee("H","销售部",1700);
Employee e9 = new Employee("I","销售部",1800);
Employee e10 = new Employee("J","财务部",1900);
Employee e11 = new Employee("K","财务部",2000);
Employee e12 = new Employee("L","财务部",2100);
Employee e13 = new Employee("M","财务部",2200);
Employee e14 = new Employee("N","财务部",2300);
// 生成树
root.add(developDep);
root.add(salesDep);
root.add(financeDep);
developDep.add(e1);
developDep.add(e2);
developDep.add(e3);
developDep.add(e4);
developDep.add(e5);
salesDep.add(e6);
salesDep.add(e7);
salesDep.add(e8);
salesDep.add(e9);
financeDep.add(e10);
financeDep.add(e11);
financeDep.add(e12);
financeDep.add(e13);
financeDep.add(e14);
// 显示公司层次
System.out.println(root.getInfo());
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);
}
}
}
}
# 控制台输出:
公司{ 姓名 ='张三', 职位 ='CEO', 薪水 ='100000'}
公司{ 姓名 ='李四', 职位 ='研发部经理', 薪水 ='12000'}
公司{ 姓名 ='A', 职位 ='研发部', 薪水 ='1000'}
公司{ 姓名 ='B', 职位 ='研发部', 薪水 ='1100'}
公司{ 姓名 ='C', 职位 ='研发部', 薪水 ='1200'}
公司{ 姓名 ='D', 职位 ='研发部', 薪水 ='1300'}
公司{ 姓名 ='E', 职位 ='研发部', 薪水 ='1400'}
公司{ 姓名 ='王五', 职位 ='销售部经理', 薪水 ='15000'}
公司{ 姓名 ='F', 职位 ='销售部', 薪水 ='1500'}
公司{ 姓名 ='G', 职位 ='销售部', 薪水 ='1600'}
公司{ 姓名 ='H', 职位 ='销售部', 薪水 ='1700'}
公司{ 姓名 ='I', 职位 ='销售部', 薪水 ='1800'}
公司{ 姓名 ='马六', 职位 ='财务部经理', 薪水 ='10000'}
公司{ 姓名 ='J', 职位 ='财务部', 薪水 ='1900'}
公司{ 姓名 ='K', 职位 ='财务部', 薪水 ='2000'}
公司{ 姓名 ='L', 职位 ='财务部', 薪水 ='2100'}
公司{ 姓名 ='M', 职位 ='财务部', 薪水 ='2200'}
公司{ 姓名 ='N', 职位 ='财务部', 薪水 ='2300'}
参考:
摘录 《设计模式(Java版)》韩敬海主编;(微信读书APP中有资源,可以直接阅读)
# 以前是免费的,不知道从什么时候起,需要15.6书币才能阅读全文了(只免费前两章了),所以只能花书币买了;
网友评论