欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计模式 | 组合模式(composite)

程序员文章站 2022-03-12 16:06:34
定义: 定义: 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 结构:(书中图,侵删) 结构:(书中图,侵删) 一个Component接口:定义统一的方法 若干树枝(Composite)类(继承Component):可包含若干个叶子(Lea ......

定义:

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

结构:(书中图,侵删)

设计模式 | 组合模式(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();
    }
}
结果输出:
[美国队长]正在移动
[美国队长]发动攻击
----------复联成立----------
美国队长加入队伍
钢铁侠加入队伍
绿巨人加入队伍
[美国队长 钢铁侠 绿巨人 ]组成的队伍正在移动
[美国队长 钢铁侠 绿巨人 ]组成的队伍发动攻击
----------发生矛盾--------
钢铁侠离开队伍
[美国队长 绿巨人 ]组成的队伍正在移动
[美国队长 绿巨人 ]组成的队伍发动攻击

总结:

这个模式用在两个事物存在一定的包含关系,但是他们的行为又是一致的,为了让客户可以方便统一的使用他们。
套用书中的话:组合模式让客户可以一致的使用组合结构和单个对象。