小Y科普: 家谱又称族谱、宗谱等。它以记载父系家族世系、人物为中心,由正史中的帝王本纪及王侯列传、年表等演变而来。是一种特殊的文献,就其内容而言,是中国五千年文明史中具备平民特点的文献,记载的是同宗共祖血缘集团世系人物和事迹等方面状况的历史图籍。编程
从最顶层的第一代J开始,一代代往下记录下去,这很明显就是一个树状结构,如今小Y要作的就是经过最合适的方式把小J的族谱图遍历出来。安全
组合模式也叫合成模式,有时又叫作部分-总体模式,主要是用来描述部分与总体的关系,将对象组合成树形结构以表示“部分-总体”的层次结构,使得用户对单个对象和组合对象的使用具备一致性。函数
Component抽象构件角色
定义参加组合对象的共有方法和属性,能够定义一些默认的行为或属性。this
Leaf叶子构件
Leaf叶子构件叶子对象,其下再也没有其余的分支,也就是遍历的最小单位。spa
Composite树枝构件
树枝对象,它的做用是组合树枝节点和叶子节点造成一个树形结构。组合模式的重点就在树枝构件。code
只要是树形结构或者只要是要体现局部和总体的关系的时候,并且这种关系还可能比较深,就要考虑一下组合模式。component
从一个总体中可以独立出部分模块或功能的场景。cdn
维护和展现部分-总体关系的场景。对象
(1)安全模式blog
①抽象构件
public abstract class Component {
//个体和总体都具备
public void operation(){
//编写业务逻辑
}
}
复制代码
②树枝构件
public class Composite extends Component {
//构件容器
private List<Component> componentArrayList = new ArrayList<Component>();
//增长一个叶子构件或树枝构件
public void add(Component component){
this.componentArrayList.add(component);
}
//删除一个叶子构件或树枝构件
public void remove(Component component){
this.componentArrayList.remove(component);
}
//得到分支下的全部叶子构件和树枝构件
public List<Component> getChildren(){
return this.componentArrayList;
}
}
复制代码
③树叶构件
public class Leaf extends Component {
/*
* 能够覆写父类方法
* public void operation(){
*
* }
*/
}
复制代码
④Client
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);
}
//经过递归遍历树
public static void showTree(Composite root){
for(Component c:root.getChildren()){
if(c instanceof Leaf){ //叶子节点
c.operation();
}else{ //树枝节点
showTree((Composite)c);
}
}
}
}
复制代码
(2)透明模式
①抽象构件
public abstract class Component {
//个体和总体都具备
public void operation(){
//编写业务逻辑
}
//增长一个叶子构件或树枝构件
public abstract void add(Component component);
//删除一个叶子构件或树枝构件
public abstract void remove(Component component);
//得到分支下的全部叶子构件和树枝构件
public abstract List<Component> getChildren();
}
复制代码
②树枝构件
public class Composite extends Component {
//构件容器
private ArrayList<Component> componentArrayList = new ArrayList<Component>();
//增长一个叶子构件或树枝构件
public void add(Component component){
this.componentArrayList.add(component);
}
//删除一个叶子构件或树枝构件
public void remove(Component component){
this.componentArrayList.remove(component);
}
//得到分支下的全部叶子构件和树枝构件
public List<Component> getChildren(){
return this.componentArrayList;
}
}
复制代码
③树叶构件
public class Leaf extends Component {
public void add(Component component){
//空实现
}
public void remove(Component component){
//空实现
}
public List<Component> getChildren(){
//空实现
}
}
复制代码
④Client
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);
}
//经过递归遍历树
public static void showTree(Component root){
for(Component c:root.getChildren()){
if(c instanceof Leaf){ //叶子节点
c.operation();
}else{ //树枝节点
showTree(c);
}
}
}
}
复制代码
安全模式在抽象组件中只定义一些默认的行为或属性,它是把树枝节点和树叶节点完全分开;透明模式是把用来组合使用的方法放到抽象类中,无论叶子对象仍是树枝对象都有相同的结构,经过判断确认是叶子节点仍是树枝节点,若是处理不当,这个会在运行期出现问题,不是很建议的方式。
安全模式与依赖倒置原则冲突;透明模式的好处就是它基本遵循了依赖倒转原则,方便系统进行扩展。
安全模式在遍历树形结构的的时候须要进行强制类型转换;在透明模式下,遍历整个树形结构是比较容易的,不用进行强制类型转换。
①抽象构件抽象族员类
public abstract class PersonMode {
//人名
private String name;
//性别
private String sex;
//年龄
private int age;
public PersonMode(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
//我的信息
public String getPersonInfo(){
String info="姓名:"+name+"\t性别:"+sex+"\t年龄:"+age;
return info;
}
}
复制代码
②树叶构件
public class PersonLeaf extends PersonMode {
//写一个构造函数
public PersonLeaf(String name, String sex, int age) {
super(name, sex, age);
}
}
复制代码
③树枝构件
public class PersonBranch extends PersonMode {
private List<PersonMode> personModeList=new ArrayList<>();
public PersonBranch(String name, String sex, int age) {
super(name, sex, age);
}
public void addPerson(PersonMode person){
this.personModeList.add(person);
}
public List<PersonMode> getPersonModeList(){
return this.personModeList;
}
}
复制代码
④Client
public class Client {
public static void main(String[] args) {
/**
* 组装小J的族谱
*/
PersonBranch personBranch=getPersonInfo();
showTree(personBranch);
}
private static PersonBranch getPersonInfo(){
//第一代J
PersonBranch OneJ=new PersonBranch("第一代J","男",150);
//第一代J的三个儿子
PersonBranch JA=new PersonBranch("JA","男",70);
PersonBranch JB=new PersonBranch("JB","男",60);
PersonBranch JC=new PersonBranch("JC","男",50);
//JA的三个儿子
PersonBranch JA1=new PersonBranch("JA1","男",40);
PersonBranch JA2=new PersonBranch("JA2","男",30);
PersonBranch JA3=new PersonBranch("JA3","男",45);
//JB的两个儿子
PersonBranch JB1=new PersonBranch("JB1","男",40);
PersonBranch JB2=new PersonBranch("JB2","男",30);
//JC的儿子小J
PersonBranch xiao_J=new PersonBranch("xiao_J","男",20);
//JA1三个儿子
PersonBranch JA1_1=new PersonBranch("JA1_1","男",18);
PersonBranch JA1_2=new PersonBranch("JA1_2","男",16);
PersonBranch JA1_3=new PersonBranch("JA1_3","男",20);
//JA3三个儿子
PersonBranch JA3_1=new PersonBranch("JA3_1","男",16);
PersonBranch JA3_2=new PersonBranch("JA3_2","男",20);
PersonBranch JA3_3=new PersonBranch("JA3_3","男",18);
//开始组装树状族谱
//组装第一代J下的三个儿子
OneJ.addPerson(JA);
OneJ.addPerson(JB);
OneJ.addPerson(JC);
//组装JA的三个儿子
JA.addPerson(JA1);
JA.addPerson(JA2);
JA.addPerson(JA3);
//组装JB的两个儿子
JB.addPerson(JB1);
JB.addPerson(JB2);
//组装JC的儿子
JC.addPerson(xiao_J);
//组装JA1的三个儿子
JA1.addPerson(JA1_1);
JA1.addPerson(JA1_2);
JA1.addPerson(JA1_3);
//组装JA3的三个儿子
JA3.addPerson(JA3_1);
JA3.addPerson(JA3_2);
JA3.addPerson(JA3_3);
return OneJ;
}
//经过递归遍历树
private static void showTree(PersonBranch root){
System.out.println(root.getPersonInfo());
for(PersonMode c:root.getPersonModeList()){
if(c instanceof PersonLeaf){ //叶子节点
System.out.println(c.getPersonInfo());
}else{ //树枝节点
showTree((PersonBranch) c);
}
}
}
}
复制代码
场景类负责树状结构的创建,并能够经过递归方式遍历整个树。
输出的结果为:
姓名:第一代J 性别:男 年龄:150
姓名:JA 性别:男 年龄:70
姓名:JA1 性别:男 年龄:40
姓名:JA1_1 性别:男 年龄:18
姓名:JA1_2 性别:男 年龄:16
姓名:JA1_3 性别:男 年龄:20
姓名:JA2 性别:男 年龄:30
姓名:JA3 性别:男 年龄:45
姓名:JA3_1 性别:男 年龄:16
姓名:JA3_2 性别:男 年龄:20
姓名:JA3_3 性别:男 年龄:18
姓名:JB 性别:男 年龄:60
姓名:JB1 性别:男 年龄:40
姓名:JB2 性别:男 年龄:30
姓名:JC 性别:男 年龄:50
姓名:xiao_J 性别:男 年龄:20
复制代码