小Y科普:家譜又稱族譜、宗譜等榨了。它以記載父系家族世系煎谍、人物為中心,由正史中的帝王本紀及王侯列傳龙屉、年表等演變而來呐粘。是一種特殊的文獻,就其內(nèi)容而言转捕,是中國五千年文明史中具有平民特色的文獻作岖,記載的是同宗共祖血緣集團世系人物和事跡等方面情況的歷史圖籍。
Now五芝,how to 實現(xiàn) 小J's 族譜痘儡。
一、小J族譜簡略版
從最頂層的第一代J開始枢步,一代代往下記錄下去沉删,這很明顯就是一個樹狀結(jié)構(gòu),現(xiàn)在小Y要做的就是通過最合適的方式把小J的族譜圖遍歷出來醉途。
二丑念、樹狀圖的拆解利器-組合模式
1.組合模式的定義
組合模式也叫合成模式,有時又叫做部分-整體模式结蟋,主要是用來描述部分與整體的關(guān)系,將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)渔彰,使得用戶對單個對象和組合對象的使用具有一致性嵌屎。
2.組合模式的角色介紹(組合模式有兩種實現(xiàn):安全模式和透明模式)
Component抽象構(gòu)件角色
定義參加組合對象的共有方法和屬性,可以定義一些默認的行為或?qū)傩浴?/p>Leaf葉子構(gòu)件
Leaf葉子構(gòu)件葉子對象恍涂,其下再也沒有其他的分支宝惰,也就是遍歷的最小單位。Composite樹枝構(gòu)件
樹枝對象再沧,它的作用是組合樹枝節(jié)點和葉子節(jié)點形成一個樹形結(jié)構(gòu)尼夺。組合模式的重點就在樹枝構(gòu)件。
3.組合模式的使用場景
只要是樹形結(jié)構(gòu)或者只要是要體現(xiàn)局部和整體的關(guān)系的時候,而且這種關(guān)系還可能比較深淤堵,就要考慮一下組合模式寝衫。
從一個整體中能夠獨立出部分模塊或功能的場景。
維護和展示部分-整體關(guān)系的場景拐邪。
4.安全模式和透明模式的具體實現(xiàn)
(1)安全模式
①抽象構(gòu)件
public abstract class Component {
//個體和整體都具有
public void operation(){
//編寫業(yè)務(wù)邏輯
}
}
②樹枝構(gòu)件
public class Composite extends Component {
//構(gòu)件容器
private List<Component> componentArrayList = new ArrayList<Component>();
//增加一個葉子構(gòu)件或樹枝構(gòu)件
public void add(Component component){
this.componentArrayList.add(component);
}
//刪除一個葉子構(gòu)件或樹枝構(gòu)件
public void remove(Component component){
this.componentArrayList.remove(component);
}
//獲得分支下的所有葉子構(gòu)件和樹枝構(gòu)件
public List<Component> getChildren(){
return this.componentArrayList;
}
}
③樹葉構(gòu)件
public class Leaf extends Component {
/*
* 可以覆寫父類方法
* public void operation(){
*
* }
*/
}
④Client
public class Client {
public static void main(String[] args) {
//創(chuàng)建一個根節(jié)點
Composite root = new Composite();
root.operation();
//創(chuàng)建一個樹枝構(gòu)件
Composite branch = new Composite();
//創(chuàng)建一個葉子節(jié)點
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){ //葉子節(jié)點
c.operation();
}else{ //樹枝節(jié)點
showTree((Composite)c);
}
}
}
}
(2)透明模式
①抽象構(gòu)件
public abstract class Component {
//個體和整體都具有
public void operation(){
//編寫業(yè)務(wù)邏輯
}
//增加一個葉子構(gòu)件或樹枝構(gòu)件
public abstract void add(Component component);
//刪除一個葉子構(gòu)件或樹枝構(gòu)件
public abstract void remove(Component component);
//獲得分支下的所有葉子構(gòu)件和樹枝構(gòu)件
public abstract List<Component> getChildren();
}
②樹枝構(gòu)件
public class Composite extends Component {
//構(gòu)件容器
private ArrayList<Component> componentArrayList = new ArrayList<Component>();
//增加一個葉子構(gòu)件或樹枝構(gòu)件
public void add(Component component){
this.componentArrayList.add(component);
}
//刪除一個葉子構(gòu)件或樹枝構(gòu)件
public void remove(Component component){
this.componentArrayList.remove(component);
}
//獲得分支下的所有葉子構(gòu)件和樹枝構(gòu)件
public List<Component> getChildren(){
return this.componentArrayList;
}
}
③樹葉構(gòu)件
public class Leaf extends Component {
public void add(Component component){
//空實現(xiàn)
}
public void remove(Component component){
//空實現(xiàn)
}
public List<Component> getChildren(){
//空實現(xiàn)
}
}
④Client
public class Client {
public static void main(String[] args) {
//創(chuàng)建一個根節(jié)點
Composite root = new Composite();
root.operation();
//創(chuàng)建一個樹枝構(gòu)件
Composite branch = new Composite();
//創(chuàng)建一個葉子節(jié)點
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){ //葉子節(jié)點
c.operation();
}else{ //樹枝節(jié)點
showTree(c);
}
}
}
}
4.安全模式和透明模式的區(qū)別
安全模式在抽象組件中只定義一些默認的行為或?qū)傩晕恳悖前褬渲?jié)點和樹葉節(jié)點徹底分開;透明模式是把用來組合使用的方法放到抽象類中扎阶,不管葉子對象還是樹枝對象都有相同的結(jié)構(gòu)汹胃,通過判斷確認是葉子節(jié)點還是樹枝節(jié)點,如果處理不當(dāng)东臀,這個會在運行期出現(xiàn)問題着饥,不是很建議的方式。
安全模式與依賴倒置原則沖突惰赋;透明模式的好處就是它基本遵循了依賴倒轉(zhuǎn)原則宰掉,方便系統(tǒng)進行擴展。
安全模式在遍歷樹形結(jié)構(gòu)的的時候需要進行強制類型轉(zhuǎn)換谤逼;在透明模式下贵扰,遍歷整個樹形結(jié)構(gòu)是比較容易的,不用進行強制類型轉(zhuǎn)換流部。
三戚绕、通過安全模式實現(xiàn)遍歷小J的族譜
①抽象構(gòu)件抽象族員類
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;
}
}
②樹葉構(gòu)件
public class PersonLeaf extends PersonMode {
//寫一個構(gòu)造函數(shù)
public PersonLeaf(String name, String sex, int age) {
super(name, sex, age);
}
}
③樹枝構(gòu)件
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){ //葉子節(jié)點
System.out.println(c.getPersonInfo());
}else{ //樹枝節(jié)點
showTree((PersonBranch) c);
}
}
}
}
場景類負責(zé)樹狀結(jié)構(gòu)的建立,并可以通過遞歸方式遍歷整個樹枝冀。
輸出的結(jié)果為:
姓名:第一代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