重学java23种设计模式(8)组合模式

跟着《软件秘笈---设计模式那点事》学习


预热:秘籍给出了这么个图


定义:

组合模式(Composite Pattern)将对象组合成属性结构以表示“部分~整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。


实例:

/**
 * 普通员工
 */
public class Employees {
	// 员工号
	private String no;
	// 员工姓名
	private String name;
	// 职位
	private String position;
	// 薪资
	private double salary;

	public Employees(String no, String name, String position, double salary) {
		this.no = no;
		this.name = name;
		this.position = position;
		this.salary = salary;
	}

	// 获得用户基本信息
	public void printUserBaseInfo() {
		System.out.println( this.no + " " + this.name + " " + this.position + "" + this.salary);
	}

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}
}

import java.util.ArrayList;

/*
 * 管理者
 * */
public class Manager {
	// 员工号
	private String no;
	// 员工姓名
	private String name;
	// 职位
	private String position;
	// 薪资
	private double salary;
	// 存储下属员工信息
	private ArrayList arrayList = new ArrayList();
	// 私有属性,长度字符串
	private int length;

	public Manager(String no, String name, String position, double salary) {
		this.no = no;
		this.name = name;
		this.position = position;
		this.salary = salary;

		// 计算总字节长度
		this.length += (no == null || "".equals(no.trim())) ? 0 : no.getBytes().length;
		this.length += (no == null || "".equals(name.trim())) ? 0 : name.getBytes().length;
		this.length += (no == null || "".equals(position.trim())) ? 0 : position.getBytes().length;
		this.length += String.valueOf(salary).getBytes().length;
	}

	/*
	 * 增加一个管理人员
	 */
	@SuppressWarnings("unchecked")
	public void add(Manager manager) {
		this.arrayList.add(manager);
	}

	/*
	 * 增加一个管理人员
	 */
	@SuppressWarnings("unchecked")
	public void add(Employees employees) {
		this.arrayList.add(employees);
	}

	// 获得用户基本信息
	public void printUserBaseInfo() {
		System.out.println(this.no + " " + this.name + " " + this.position + "" + this.salary);
	}

	/*
	 * 打印员工信息
	 */
	public void printEmployeesInfo(int layer) {
		int tmpLayer = ++layer;
		for (int i = 0; i < this.arrayList.size(); i++) {
			Object object = this.arrayList.get(i);
			if (object == null)
				continue;
			// 判断是管理人员还是工作人员
			if (object instanceof Employees) {
				// 如果是员工,则输出员工基本信息
				// 打印'-'
				printChar(tmpLayer);
				//打印员工基本信息
				((Employees)object).printUserBaseInfo();
			} else if (object instanceof Manager) {
				//如果是管理人员,则输出管理者基本信息然后输出管理者手下员工信息
				// 打印'-'
				printChar(tmpLayer);
				//实例化管理者
				Manager manager  = (Manager)object; 
				//打印管理者基本信息
				manager.printUserBaseInfo();
				//打印管理者手下员工信息
				manager.printEmployeesInfo(tmpLayer);
			}
		}

	}

	// 打印若干字符
	protected void printChar(int layer) {
		for (int j = 0; j < layer * 2; j++) {
			System.out.print("-");
		}
	}

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}
}

import com.demo.common.Employees;
import com.demo.common.Manager;

public class ClientCommon {
	public static void main(String[] args) {
		//公司CEO
		Manager boss = new Manager("1","大老板","CEO",100000);
		/*
		 * CEO手下若干部门经理
		 * */
		Manager financeManager = new Manager("11","张总","财务部经理",60000);
		Manager personnelManager = new Manager("12","王总","人事部经理",60000);
		Manager technacalManager = new Manager("13","陈总","技术部经理",60000);

		/*
		 * 技术部门还有助理和若干主管
		 * */
		Manager deptAssistant = new Manager("1301","王助理","部门助理",2000);
		Manager deptManager1 = new Manager("1302","主管 1","技术主管",3000);
		/*
		 * 技术主管下面有工程师(最终干活的人)
		 * */
		Employees  softwareEmployeer1 = new Employees("1302001","张三","软件工程师",5000);
		Employees  softwareEmployeer2 = new Employees("1302002","李四","软件工程师",5500);
		Employees  softwareEmployeer3 = new Employees("1302003","王五","软件工程师",4500);
		
		//技术主管 1,添加员工信息
		deptManager1.add(softwareEmployeer1);
		deptManager1.add(softwareEmployeer2);
		deptManager1.add(softwareEmployeer3); 
		
		Manager deptManager2 = new Manager("1303","主管 2","技术主管",3000);
		
		//技术部经理添加下属
		technacalManager.add(deptAssistant);
		technacalManager.add(deptManager1);
		technacalManager.add(deptManager2);
		
		Manager marketingManager = new Manager("14","吴总","市场部经理",60000);
		
		//为CEO添加部门经理
		boss.add(financeManager);
		boss.add(personnelManager);
		boss.add(technacalManager);
		boss.add(marketingManager);
		
		//打印CEO和下属信息
		boss.printUserBaseInfo();
		boss.printEmployeesInfo(1);
	}
}
上面的例子中无论管理者还是普通员工都包含基本信息等,这样可以讲管理者和员工狗抽象出一个父类,但这并不好,原因是管理者和员工狗被区别对待了,不能统一管理,可以这样实现,讲增减员工信息方法作为抽象方法没放到抽象父类中,由子类实现,作为员工狗没有下属没抽象方法是一个空方法,就可以统一对待每一个员工了,无论是管理者还是普通员工。

下面是组合模式实现

/*
 * 职工类接口
 * */
public abstract class Staff {
	// 员工号
	private String no;
	// 员工姓名
	private String name;
	// 职位
	private String position;
	// 薪资
	private double salary;
	// 私有属性,长度
	private int length;

	public Staff(String no, String name, String position, double salary) {
		this.no = no;
		this.name = name;
		this.position = position;
		this.salary = salary;

		// 计算总字节长度
		this.length += (no == null || "".equals(no.trim())) ? 0 : no.getBytes().length;
		this.length += (no == null || "".equals(name.trim())) ? 0 : name.getBytes().length;
		this.length += (no == null || "".equals(position.trim())) ? 0 : position.getBytes().length;
		this.length += String.valueOf(salary).getBytes().length;
	}

	public void printUserBaseInfo() {
		System.out.println(this.no + " " + this.name + " " + this.position + "" + this.salary);
	}

	// 添加员工信息
	public abstract void add(Staff staff);

	// 删除员工
	public abstract Staff remove(String no);

	// 打印员工信息
	public abstract void printEmployeesInfo(int layer);
	
	// 打印若干字符
	protected void printChar(int layer) {
		for (int j = 0; j < layer * 2; j++) {
			System.out.print("-");
		}
	}
	// 私有方法打印一行
	protected void printLine() {
		System.out.println("+");
		for (int i = 0; i < this.length + 4; i++) {
			System.out.print("-");
		}
		System.out.println("-");
	}

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}
}

/*
 * 管理者
 * */
public class Manager extends Staff {

	private ArrayList<Staff> arrayList = new ArrayList<Staff>();

	public Manager(String no, String name, String position, double salary) {
		super(no, name, position, salary);
	}

	@Override
	public void add(Staff staff) {
		this.arrayList.add(staff);
	}

	@Override
	public Staff remove(String no) {
		Staff staff = null;

		if (no != null && !"".equals(no)) {
			for (int i = 0; i < this.arrayList.size(); i++) {
				if (this.arrayList.get(i) == null) {
					continue;
				} else {
					staff = this.arrayList.remove(i);
					break;
				}
			}
		}

		return staff;
	}

	@Override
	public void printEmployeesInfo(int layer) {
		int tmpLayer = ++layer;
		for (int i = 0; i < this.arrayList.size(); i++) {
			if (this.arrayList.get(i) == null) {
				continue;
			}
			// 如果是管理人员,则输出管理者基本信息然后输出管理者手下员工信息
			// 打印'-'
			printChar(tmpLayer);
			// 打印管理者基本信息
			this.arrayList.get(i).printUserBaseInfo();
			// 打印管理者手下员工信息
			this.arrayList.get(i).printEmployeesInfo(tmpLayer);
		}
	}
}

import com.demo.composite.Staff;

/**
 * 普通员工
 */
public class Employees extends Staff {
	public Employees(String no, String name, String position, double salary) {
		super(no, name, position, salary);
	}

	@Override
	public void add(Staff staff) {
		return;
	}

	@Override
	public Staff remove(String no) {
		return null;
	}

	@Override
	public void printEmployeesInfo(int layer) {
		return;
	}

}

import com.demo.composite.Staff;
import com.demo.composite.sub.Employees;
import com.demo.composite.sub.Manager;

public class Client {
	public static void main(String[] args) {
		//公司CEO
		Staff boss = new Manager("1","大老板","CEO",100000);
		/*
		 * CEO手下若干部门经理
		 * */
		Staff financeManager = new Manager("11","张总","财务部经理",60000);
		Staff personnelManager = new Manager("12","王总","人事部经理",60000);
		Staff technacalManager = new Manager("13","陈总","技术部经理",60000);

		/*
		 * 技术部门还有助理和若干主管
		 * */
		Staff deptAssistant = new Manager("1301","王助理","部门助理",2000);
		Staff deptManager1 = new Manager("1302","主管 1","技术主管",3000);
		/*
		 * 技术主管下面有工程师(最终干活的人)
		 * */
		Staff  softwareEmployeer1 = new Employees("1302001","张三","软件工程师",5000);
		Staff  softwareEmployeer2 = new Employees("1302002","李四","软件工程师",5500);
		Staff  softwareEmployeer3 = new Employees("1302003","王五","软件工程师",4500);
		
		//技术主管 1,添加员工信息
		deptManager1.add(softwareEmployeer1);
		deptManager1.add(softwareEmployeer2);
		deptManager1.add(softwareEmployeer3); 
		
		Staff deptManager2 = new Manager("1303","主管 2","技术主管",3000);
		
		//技术部经理添加下属
		technacalManager.add(deptAssistant);
		technacalManager.add(deptManager1);
		technacalManager.add(deptManager2);
		
		Staff marketingManager = new Manager("14","吴总","市场部经理",60000);
		
		//为CEO添加部门经理
		boss.add(financeManager);
		boss.add(personnelManager);
		boss.add(technacalManager);
		boss.add(marketingManager);
		
		//打印CEO和下属信息
		boss.printUserBaseInfo();
		boss.printEmployeesInfo(1);
	}
}


分析:

组合模式让我们在树形结构的问题中模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使客户程序与复杂元素的内部结构解耦。

体现的设计原则:

1:统一对待个别对象和组合对象

2:面向对象变成


使用场合:

(1)想表示对象的部分-整体层次结构

(2)希望用户忽略组合对象和单个对象的不同,用于将统一使用组合结构中的所有对象的时候。


参考资料:

《软件秘笈---设计模式那点事》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值