从王者荣耀看设计模式(组合模式)
一.简介
在王者荣耀这款游戏中,我们可以在商店中购买英雄。英雄由法师、射手、打野等职业组合而成,其中各个职业由中国元素的英雄和外国元素的英雄组成,玩家可根据需要挑选并购买英雄
二.组合模式
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
模式动机
在面向对象系统中,我们常常遇到一类具有“容器”特征的对象——即它们在充当普通对象的同时,又可作为其他对象的容器,这些对象称为容器对象。而那些只能充当普通对象的对象则称为叶子对象。想到组合模式就应该想到树形结构图。组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分。在本实例中,中国元素英雄和外国元素英雄组成各类职业,各类职业组成全体可供选择英雄。
- 这其中的设计原则有:
- 组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。
- 组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因。
- 组合模式必须包含的内容:
组合部件(Component):它是一个抽象角色,为要组合的对象提供统一的接口。
叶子(Leaf):在组合中表示子节点对象,叶子节点不能有子节点。
合成部件(Composite):定义有枝节点的行为,用来存储部件,实现在Component接口中的有关操作,如增加(Add)和删除(Remove)。
- 组合模式模式的优点
- 组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
- 将”客户代码与复杂的对象容器结构“解耦。
- 可以更容易地往组合对象中加入新的构件。
- 组合模式模式的缺点
- 使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。(这个是几乎所有设计模式所面临的问题)。
- 组合模式适用场景
- 当想表达对象的部分-整体的层次结构时。
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。
三.结构图
四.设计类图
五.代码实现
Type类(组合部件):为要组合的对象提供统一的接口
package com.game.heroShop;
/*
* 组合部件(抽象角色)为要组合的对象提供统一的接口
*/
public abstract class Type {
//设置组合部件的名称
private String rootName;
//创建有参的构造方法
public Type(String rootName) {
super();
this.rootName = rootName;
}
//创建无参的构造方法
public Type() {
}
//get.set
public String getName() {
return rootName;
}
public void setName(String rootName) {
this.rootName = rootName;
}
//为要组合的对象提供接口add
public abstract void add(Type heroType);
//为要组合的对象提供接口remove
public abstract void romove(Type heroType);
//为要组合的对象提供接口display
public abstract void display(int depth);
}
ProfessionType类(合成部件类):实现接口中有关操作
package com.game.heroShop;
import java.util.ArrayList;
import java.util.List;
/*
* 合成部件类
* 定义有枝节点的行为,用来存储部件,实现在Component接口中的有关操作,如增加(Add)和删除(Remove)
*/
public class ProfessionType extends Type {
//定义集合类存放Type类型
private List<Type> cList;
//创建无参的够着函数,初始化集合
public ProfessionType() {
cList = new ArrayList<Type>();
}
//创建有参的够着函数,初始化集合
public ProfessionType(String name) {
super(name);
cList = new ArrayList<Type>() ;
}
//实现组合部件接口中的add操作
public void add(Type heroType) {
cList.add(heroType);
}
//实现组合部件接口中的remove操作
public void romove(Type heroType) {
cList.remove(heroType);
}
//实现组合部件接口中的display操作
public void display(int depth) {
// TODO Auto-generated method stub
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
for (Type c : cList) {
c.display(depth + 2);
}
}
}
ClassificationA类(叶子类),表示子节点对象
package com.game.heroShop;
/*
*叶子类,在组合中表示子节点对象,叶子节点不能有子节点。
*/
public class ClassificationA extends Type {
//创建有参的构造方法
public ClassificationA(String heroName) {
super(heroName);
}
//实现组合部件接口中的相关操作
public void add(Type heroName) {}
public void romove(Type heroName) {}
public void display(int depth) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
}
}
ClassificationB类(叶子类),表示子节点对象
package com.game.heroShop;
/*
*叶子类,在组合中表示子节点对象,叶子节点不能有子节点。
*/
public class ClassificationB extends Type {
//创建有参的构造方法
public ClassificationB(String heroName) {
super(heroName);
}
//实现组合部件接口中的相关操作
public void add(Type heroName) {}
public void romove(Type heroName) {}
public void display(int depth) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < depth; i++) {
sb.append("-");
}
System.out.println(new String(sb) + this.getName());
}
}
HeroShopTest类(测试类)
package com.game.heroShopTest;
/*
* 测试类
*/
import com.game.heroShop.ClassificationB;
import com.game.heroShop.ProfessionType;
import com.game.heroShop.ClassificationA;
import com.game.heroShop.Type;
public class HeroShopTest {
public static void main(String[] args) {
//创建合成部件实例
Type root=new ProfessionType();
root.setName("所有英雄");
//法师,射手,打野组合成所有英雄
Type master = new ProfessionType("法师");
Type shooter = new ProfessionType("射手");
Type killBeast = new ProfessionType("打野");
root.add(master);
root.add(shooter);
root.add(killBeast);
//中国法师和外国法师组合成法师职业
Type master1=new ProfessionType("中国法师");
Type master2=new ProfessionType("外国法师");
master.add(master1);
master.add(master2);
//中国法师由钟馗等英雄组合而成
master1.add(new ClassificationB("钟馗"));
//外国法师由米莱迪等英雄组合而成
master2.add(new ClassificationB("米莱迪"));
//中国射手和外国射手组合成射手职业
Type shooter1=new ProfessionType("中国射手");
Type shooter2=new ProfessionType("外国射手");
shooter.add(shooter1);
shooter.add(shooter2);
//中国射手由鲁班七号和虞姬等英雄组合而成
shooter1.add(new ClassificationA("鲁班七号"));
shooter1.add(new ClassificationA("虞姬"));
//外国射手由马可波罗等英雄组合而成
shooter2.add(new ClassificationA("马可波罗"));
//中国打野和外国打野组合成打野职业
Type killBeast1=new ProfessionType("中国打野");
Type killBeast2=new ProfessionType("外国打野");
killBeast.add(killBeast1);
killBeast.add(killBeast2);
//中国打野由李白,韩信等英雄组合而成
killBeast1.add(new ClassificationA("韩信"));
killBeast1.add(new ClassificationA("李白"));
//外国打野由宫本武藏等英雄组合而成
killBeast2.add(new ClassificationA("宫本武藏"));
root.display(0);
}
}