設計模式 | 組合模式(composite)

定義:

將對象組合成樹形結構以表示「部分-總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。

結構:(書中圖,侵刪)

 

一個Component接口:定義統一的方法
若干樹枝(Composite)類(繼承Component):可包含若干個葉子(Leaf)節點
若干樹葉(Leaf)類:葉子節點
 
書中說到這個模式有兩種方式:
透明方式:在Component接口中定義添加和移除子節點的方法,可是葉子節點不須要這兩個方法。這樣寫能夠保持客戶端調用的一致性。
安全方式:不在Component接口中定義添加和移除子節點的方法,直接在葉子節點中定義,這樣寫省去了葉子節點中的無用代碼,可是客戶端須要添加判斷。

實例:

書中舉到一個例子說是,假如你在word修改字體的大小時,你修改一個字和一段文字操做都是相同的。用戶不用對此有差異操做,程序也不用差異對待。
而後,就讓我想到了遊戲中的隊伍系統,在某些遊戲裏是能夠跟隨的,隊長操縱本身,整個隊伍都會跟着一塊兒行動,和隊長一我的行動沒有什麼區別。
 
玩家操縱的目標接口(Component):
package designpattern.composite;

public abstract class Target {
    private String name;// 名稱

    public abstract void add(Target target);// 增長節點

    public abstract void remove(Target target);// 刪除節點

    public abstract void move();// 移動

    public abstract void attack();// 攻擊

    public String getName() {
        return name;
    }

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

}
玩家類(Leaf):
package designpattern.composite;

public class Player extends Target {
    private String name;

    public Player(String name) {
        super();
        this.name = name;
    }

    @Override
    public void move() {
        System.out.println("[" + name + "]正在移動");
    }

    @Override
    public void attack() {
        System.out.println("[" + name + "]發動攻擊");
    }

    @Override
    public void add(Target target) {
    }

    @Override
    public void remove(Target target) {
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Player [name=" + name + "]";
    }

}
隊伍類(Composite):
package designpattern.composite;

import java.util.ArrayList;
import java.util.List;

public class Team extends Target {
    List<Target> team = new ArrayList<>();

    @Override
    public void add(Target target) {
        team.add(target);
        System.out.println(target.getName() + "加入隊伍");
    }

    @Override
    public void remove(Target target) {
        team.remove(target);
        System.out.println(target.getName() + "離開隊伍");
    }

    @Override
    public void move() {
        System.out.println(teamMembers() + "組成的隊伍正在移動");
    }

    @Override
    public void attack() {
        System.out.println(teamMembers() + "組成的隊伍發動攻擊");
    }

    private String teamMembers() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("[");
        for (Target target : team) {
            stringBuffer.append(target.getName() + " ");
        }
        stringBuffer.append("]");
        return stringBuffer.toString();
    }
}
客戶端:
package designpattern.composite;

public class Client {
    public static void main(String[] args) {
        Player captainAmerica = new Player("美國隊長");
        captainAmerica.move();
        captainAmerica.attack();

        System.out.println("----------復聯成立----------");
        Player ironMan = new Player("鋼鐵俠");
        Player hulk = new Player("綠巨人");
        Team team = new Team();
        team.add(captainAmerica);
        team.add(ironMan);
        team.add(hulk);

        team.move();
        team.attack();

        System.out.println("----------發生矛盾--------");
        team.remove(ironMan);

        team.move();
        team.attack();
    }
}
結果輸出:
[美國隊長]正在移動
[美國隊長]發動攻擊
----------復聯成立----------
美國隊長加入隊伍
鋼鐵俠加入隊伍
綠巨人加入隊伍
[美國隊長 鋼鐵俠 綠巨人 ]組成的隊伍正在移動
[美國隊長 鋼鐵俠 綠巨人 ]組成的隊伍發動攻擊
----------發生矛盾--------
鋼鐵俠離開隊伍
[美國隊長 綠巨人 ]組成的隊伍正在移動
[美國隊長 綠巨人 ]組成的隊伍發動攻擊

總結:

這個模式用在兩個事物存在必定的包含關係,可是他們的行爲又是一致的,爲了讓客戶能夠方便統一的使用他們。
套用書中的話:組合模式讓客戶能夠一致的使用組合結構和單個對象。
相關文章
相關標籤/搜索