组合模式(Bridge Pattern) – 设计模式之结构型模式:
目录
组合模式(Component Pattern)
定义: Compose objects into tree structures to represent part-whole hierarchies. Composit clients treat individual objects and compositions of objects uniformly.
将对象组合成树形结构以表示‘部分整体’的层次结构。 组合模式使得用户对单个对象和组合对象的使用具有一致性。
当需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式。
类图
组合模式通用的类图
抽象构件 Component 它是组合模式的精髓, 定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性
常见的组合内容:
字符 单词 句子 段落 文章
水滴 水流 小溪 江河 大海
员工 部门 公司
例子1:
过程:
类图:
代码:
抽象组件:PlayerComposite
public abstract class PlayerComposite {
public abstract void add(PlayerComposite player);
public abstract void remove(PlayerComposite player);
public abstract void display();
}
球员:BasketPlayer
public class BasketPlayer extends PlayerComposite {
private String name;
private String role;
private int age;
public BasketPlayer(String name, String role,int age) {
this.name = name;
this.role = role;
this.age = age;
}
@Override
public String toString() {
return "{" +
"name='" + name + '\'' +
", role='" + role + '\'' +
", age=" + age +
'}';
}
@Override
public void add(PlayerComposite player) {
//
}
@Override
public void remove(PlayerComposite player) {
//
}
@Override
public void display() {
//
}
}
球队: PlayerComposite
public class BasketTeams extends PlayerComposite {
private String name;
private String position;
private List<PlayerComposite> basketPlayers;
public BasketTeams(String name, String position,List<PlayerComposite> basketPlayers) {
this.name = name;
this.position = position;
this.basketPlayers = basketPlayers;
}
public BasketTeams(BasketPlayer... basketPlayers) {
for (BasketPlayer basketPlayer : basketPlayers) {
this.add(basketPlayer);
}
}
@Override
public void add(PlayerComposite player) {
this.basketPlayers.add(player);
}
@Override
public void remove(PlayerComposite player) {
this.basketPlayers.remove(player);
}
@Override
public void display() {
System.out.println("球队: "+name+" 位于:"+position +" 队伍里面有:");
basketPlayers.forEach(e -> System.out.println(e.toString()));
}
}
联盟: BasketLeager
public class BasketLeager extends PlayerComposite {
private String name;
private List<PlayerComposite> basketTeams;
public BasketLeager(String name, List<PlayerComposite> basketTeams) {
this.name = name;
this.basketTeams = basketTeams;
}
@Override
public void add(PlayerComposite player) {
this.basketTeams.add(player);
}
@Override
public void remove(PlayerComposite player) {
this.basketTeams.remove(player);
}
@Override
public void display() {
System.out.println("篮球联盟: "+name+" 球队有 ");
basketTeams.forEach(PlayerComposite::display);
}
}
测试
球员测试:
public class PlayerTest {
public static void main(String[] args) {
PlayerComposite brown = new BasketPlayer("Brown","Small Forward",23);
PlayerComposite tatum = new BasketPlayer("Tatum","Power Forward",22);
PlayerComposite walk = new BasketPlayer("Walk","Point Guard",29);
PlayerComposite mike = new BasketPlayer("Mike","Point Guard",35);
List<PlayerComposite> basketPlayers = Lists.newArrayList(
brown,tatum,walk,mike
);
PlayerComposite cellticTeam = new BasketTeams("凯尔特人", "东部",basketPlayers);
cellticTeam.display();
// 转会来的球员
PlayerComposite aoJielie = new BasketPlayer("AoJielie", "Center", 22);
cellticTeam.add(aoJielie);
// 转会走的球员
cellticTeam.remove(mike);
System.out.println("====== change ===========");
cellticTeam.display();
}
}
结果:
球队: 凯尔特人 位于:东部 队伍里面有:
{name='Brown', role='Small Forward', age=23}
{name='Tatum', role='Power Forward', age=22}
{name='Walk', role='Point Guard', age=29}
{name='Mike', role='Point Guard', age=35}
====== 交易后球队情况 ===========
球队: 凯尔特人 位于:东部 队伍里面有:
{name='Brown', role='Small Forward', age=23}
{name='Tatum', role='Power Forward', age=22}
{name='Walk', role='Point Guard', age=29}
{name='AoJielie', role='Center', age=22}
球队测试:
public class TeamTest {
public static void main(String[] args) {
PlayerComposite celtics = initTeamCel();
PlayerComposite laker = initTeamLaker();
List<PlayerComposite> basketTeams = Lists.newArrayList(
celtics, laker
);
PlayerComposite basketLeager = new BasketLeager("NBA 联盟", basketTeams);
basketLeager.display();
// 新增加的球队
PlayerComposite warrior = initTeamWarri();
basketLeager.add(warrior);
// 从联盟退出的球队
basketLeager.remove(celtics);
System.out.println("====== change ===========");
basketLeager.display();
}
public static PlayerComposite initTeamCel(){
PlayerComposite brown = new BasketPlayer("Brown","Small Forward",23);
PlayerComposite tatum = new BasketPlayer("Tatum","Power Forward",22);
PlayerComposite walk = new BasketPlayer("Walk","Point Guard",29);
PlayerComposite mike = new BasketPlayer("Mike","Point Guard",35);
List<PlayerComposite> basketPlayers = Lists.newArrayList(
brown,tatum,walk,mike
);
return new BasketTeams("凯尔特人", "东部",basketPlayers);
}
public static PlayerComposite initTeamLaker(){
PlayerComposite james = new BasketPlayer("詹姆斯","小前锋",37);
PlayerComposite shat = new BasketPlayer("浓眉","大前锋",28);
PlayerComposite pork = new BasketPlayer("加索尔","中锋",32);
List<PlayerComposite> basketPlayers = Lists.newArrayList(
james,shat,pork
);
return new BasketTeams("湖人队", "西部",basketPlayers);
}
public static PlayerComposite initTeamWarri(){
PlayerComposite cury = new BasketPlayer("库里","控球后卫",31);
PlayerComposite green = new BasketPlayer("格林","大前锋",28);
PlayerComposite tom = new BasketPlayer("汤普森","得分后卫",32);
List<PlayerComposite> basketPlayers = Lists.newArrayList(
cury,green,tom
);
return new BasketTeams("勇士队", "西部",basketPlayers);
}
}
结果:
篮球联盟: NBA 联盟 球队有
球队: 凯尔特人 位于:东部 队伍里面有:
{name='Brown', role='Small Forward', age=23}
{name='Tatum', role='Power Forward', age=22}
{name='Walk', role='Point Guard', age=29}
{name='Mike', role='Point Guard', age=35}
球队: 湖人队 位于:西部 队伍里面有:
{name='詹姆斯', role='小前锋', age=37}
{name='浓眉', role='大前锋', age=28}
{name='加索尔', role='中锋', age=32}
====== change ===========
篮球联盟: NBA 联盟 球队有
球队: 湖人队 位于:西部 队伍里面有:
{name='詹姆斯', role='小前锋', age=37}
{name='浓眉', role='大前锋', age=28}
{name='加索尔', role='中锋', age=32}
球队: 勇士队 位于:西部 队伍里面有:
{name='库里', role='控球后卫', age=31}
{name='格林', role='大前锋', age=28}
{name='汤普森', role='得分后卫', age=32}
总结:
优点:
1、高层模块调用简单。
2、节点*增加和删除。
缺点:
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分--整体场景,如树形菜单,文件、文件夹的管理,员工、部门
除去对节点的操作,组合模式的类图像不像模板模式? 尤其是抽象组件 是模板方法里面的抽象方法(Abstract Method),加具体方法就是一个模板方法了。