努力的小胖学习记录(十)------多路分发

由于这次的东西比较简单,只是一个概念性的东西。所以先从一个游戏例子开始(石头剪刀布),假设我定义了这么一个接口

/**
 * 石头:ItemOne
 * 剪:ItemTwo
 * 刀布:ItemThree
 * 游戏
 * @author Administrator
 *
 */
public interface Item {
	String compete(Item item);	
	String getName();
}

石头,剪刀,布一样都是item的实例,他们都可以和另外一个item比较。下面我按照不同的方式实现每一个类

  • 石头(单路分发)
    这一种可能我们初级阶段经常会这样写的一种方式
/**
 * 石头
 * @author Administrator
 *
 */
public class ItemOne implements Item{

	@Override
	public String compete(Item item) {
		if(item instanceof ItemOne) {
			return "0";
		}
		if(item instanceof ItemTwo) {
			return "1";
		}
		if(item instanceof ItemThree) {
			return "-1";
		}
		return null;
	}
	@Override
	public String getName() {
		return "石头";
	}
}

测试结果
单路分发测试结果
这种实现方式其实本质上是可以实现功能,而且简单易懂,唯一的缺点就是后期新增了一个Item的话,这个方法必须修改,这就违反开闭原则

  • 剪刀(普通二路)
    这里需要改一下item接口,新增被每一个item比较的方法(有多少个实例就需要加多少个)
/**
 * 石头:ItemOne
 * 剪:ItemTwo
 * 刀布:ItemThree
 * 游戏
 * @author Administrator
 *
 */
public interface Item {
	String compete(Item item);//比较this vs item
	String itemCompeteThis(ItemOne itemOne);//石头 vs this
	String itemCompeteThis(ItemTwo itemTwo);//剪刀 vs this
	String itemCompeteThis(ItemThree itemThree);//布 vs this
	String getName();
}

剪刀实现类

/**
 * 剪刀
 * @author Administrator
 *
 */
public class ItemTwo implements Item{

	@Override
	public String compete(Item item) {
		return item.itemCompeteThis(this);
	}
	@Override
	public String itemCompeteThis(ItemOne itemOne) {
		return "1";
	}
	@Override
	public String itemCompeteThis(ItemTwo itemTwo) {
		return "0";
	}
	@Override
	public String itemCompeteThis(ItemThree itemThree) {
		return "-1";
	}
	@Override
	public String getName() {
		return "剪刀";
	}
}

测试结果
测试结果
这个看起来比第一个确实好多了,如果在新增一个item的情况下,只需要重载一个itemCompeteThis方法,没有违背开闭原则,但是需要知道有多少个实现类

  • 布(使用枚举实现多路分发)
    这里的核心是使用一个枚举维护好所有item比对其他item的结果,代码如下
package com.javaSe.distribute;
/**
 * 剪刀
 * @author Administrator
 *
 */
public class ItemThree{
	public static enum Item{
		ItemOne("石头","0","1","-1"),
		ItemTwo("剪刀","-1","0","1"),
		ItemThree("布","1","-1","0")
		;
		private String name,vItemOne,vItemTwo,vItemThree;
		private Item(String name,String vItemOne, String vItemTwo, String vItemThree) {
			this.name = name;
			this.vItemOne = vItemOne;
			this.vItemTwo = vItemTwo;
			this.vItemThree = vItemThree;
		}
		
		public String getName() {
			return name;
		}
		public String compete(Item item) {
			switch (item) {
			case ItemOne:
				return vItemOne;
			case ItemTwo:
				return vItemTwo;
			case ItemThree:
				return vItemThree;
			default:
				return "";
			}
		}
	}

//	@Override
//	public String compete(Item item) {
//		return item.compete(this);
//	}
//	@Override
//	public String itemCompeteThis(ItemOne itemOne) {
//		return "-1";
//	}
//	@Override
//	public String itemCompeteThis(ItemTwo itemTwo) {
//		return "1";
//	}
//	@Override
//	public String itemCompeteThis(ItemThree itemThree) {
//		return "0";
//	}
//	@Override
//	public String getName() {
//		return "布";
//	}

}

测试结果
测试结果
个人认为,这个方式的唯一优点就是代码简洁了。

  • 总结
    通过上面的例子,相信大家可能知道什么是分发的概念了。其实java是只支持单路分发的,也就是说,如果要执行的操作包含了不止一个类型位置的对象时,那么java动态绑定只能处理一个未知对象,这时我们就需要使用多个方法确定多个未知对象,每个方法调用确定一个未知对象,这就叫多路分发。需要注意的是,要利用多路分发,就必须为每一个类型提供实际的方法调用,这在实现类很多的情况下,会变得很臃肿。这时可以考虑别的方式来处理这种问题了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值