从王者荣耀看设计模式(四.组合模式)

从王者荣耀看设计模式(组合模式)

一.简介

在王者荣耀这款游戏中,我们可以在商店中购买英雄。英雄由法师、射手、打野等职业组合而成,其中各个职业由中国元素的英雄和外国元素的英雄组成,玩家可根据需要挑选并购买英雄

二.组合模式

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

模式动机
在面向对象系统中,我们常常遇到一类具有“容器”特征的对象——即它们在充当普通对象的同时,又可作为其他对象的容器,这些对象称为容器对象。而那些只能充当普通对象的对象则称为叶子对象。想到组合模式就应该想到树形结构图。组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分。在本实例中,中国元素英雄和外国元素英雄组成各类职业,各类职业组成全体可供选择英雄。

  • 这其中的设计原则有:
  1. 组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。
  2. 组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因。
  3. 组合模式必须包含的内容:

组合部件(Component):它是一个抽象角色,为要组合的对象提供统一的接口。
叶子(Leaf):在组合中表示子节点对象,叶子节点不能有子节点。
合成部件(Composite):定义有枝节点的行为,用来存储部件,实现在Component接口中的有关操作,如增加(Add)和删除(Remove)。

  • 组合模式模式的优点
    1. 组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
    2. 将”客户代码与复杂的对象容器结构“解耦。
    3. 可以更容易地往组合对象中加入新的构件。
  • 组合模式模式的缺点
    1. 使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。(这个是几乎所有设计模式所面临的问题)。
  • 组合模式适用场景
    1. 当想表达对象的部分-整体的层次结构时。
    2. 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。
三.结构图

结构图

四.设计类图

类图

五.代码实现

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);
	}
}
六.运行结果

结果

七.源代码下载

从王者荣耀看设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值