文档章节

java实现多路分发

刘小米_思聪
 刘小米_思聪
发布于 2014/12/01 15:31
字数 723
阅读 368
收藏 16

多路分发就是指在调用a.plus(b),a和b都不知道确切类型,也能让他们正常交互。

    如果想使用两路分发,那么必须有两个方法调用,第一个方法调用决定第一个未知类型,第二个方法调用决定第二个未知类型。要利用多路分发,程序员必须为每一个类型提供给一个实际的方法调用。一般而言,程序员需要设定好某种配置,以便一个方法调用能够引出更多的方法调用,从而能在这个过程中处理多个类型。

   下面是个“石头 剪刀 布”(RoShamBo)游戏的例子 (from: thinking in java):

[java]  view plain copy
  1. public enum Outcome { WIN, LOSE, DRAW } ///枚举类型:赢,输,平局 
  2.   
  3.   
  4. interface Item {  
  5.     Outcome compete(Item it);  
  6.   
  7.     Outcome eval(Paper p);  
  8.   
  9.     Outcome eval(Scissors s);  
  10.   
  11.     Outcome eval(Rock r);  
  12. }  
  13.   
  14. class Paper implements Item {  
  15.     public Outcome compete(Item it) {  
  16.         return it.eval(this);  
  17.     }  
  18.   
  19.     public Outcome eval(Paper p) {  
  20.         return DRAW;  
  21.     }  
  22.   
  23.     public Outcome eval(Scissors s) {  
  24.         return WIN;  
  25.     }  
  26.   
  27.     public Outcome eval(Rock r) {  
  28.         return LOSE;  
  29.     }  
  30.   
  31.     public String toString() {  
  32.         return "Paper";  
  33.     }  
  34. }  
  35.   
  36. class Scissors implements Item {  
  37.     public Outcome compete(Item it) {  
  38.         return it.eval(this);  
  39.     }  
  40.   
  41.     public Outcome eval(Paper p) {  
  42.         return LOSE;  
  43.     }  
  44.   
  45.     public Outcome eval(Scissors s) {  
  46.         return DRAW;  
  47.     }  
  48.   
  49.     public Outcome eval(Rock r) {  
  50.         return WIN;  
  51.     }  
  52.   
  53.     public String toString() {  
  54.         return "Scissors";  
  55.     }  
  56. }  
  57.   
  58. class Rock implements Item {  
  59.     public Outcome compete(Item it) {  
  60.         return it.eval(this);  
  61.     }  
  62.       
  63.     public Outcome eval(Paper p) {  
  64.         return WIN;  
  65.     }  
  66.   
  67.     public Outcome eval(Scissors s) {  
  68.         return LOSE;  
  69.     }  
  70.   
  71.     public Outcome eval(Rock r) {  
  72.         return DRAW;  
  73.     }  
  74.   
  75.     public String toString() {  
  76.         return "Rock";  
  77.     }  
  78. }  
  79.   
  80. public class RoShamBo1 {  
  81.     static final int SIZE = 20;  
  82.     private static Random rand = new Random(47);  
  83.   
  84.     public static Item newItem() {  
  85.         switch (rand.nextInt(3)) {  
  86.         default:  
  87.         case 0:  
  88.             return new Scissors();  
  89.         case 1:  
  90.             return new Paper();  
  91.         case 2:  
  92.             return new Rock();  
  93.         }  
  94.     }  
  95.   
  96.     public static void match(Item a, Item b) {  
  97.         System.out.println(a + " vs. " + b + ": " + a.compete(b));  
  98.     }  
  99.   
  100.     public static void main(String[] args) {  
  101.         for (int i = 0; i < SIZE; i++)  
  102.             match(newItem(), newItem());  
  103.     }  
  104. }   

RoshamBol.match()有2个item参数,通关过Item.compete()方法开始2路分发,要判定a的类型,分发机制会在a的实际类型的compete()内部起到分发作用。compete()方法通关过eval()来为另一个类型实现第二次分发, 将自身(this)作为参数调用eval(),能够调用重载过的eval()方法,这能够保留第一次分发的类型信息,第二次分发完成时,就能知道两个Item对象的具体类型了。

因此,试着执行一下上述的main函数,match(newItem(),newItem())中的两个参数是生成的两个随机的对象,假设某次随机的 match(newItem(), newItem()) 为match(paper,scissor)。那么调用paper.compete(scissor),又paper.compete(scissor){ return scissor.eval(paper)},故而调用Scissor对象的eval(Paper paper)方法,返回Lose。因此main函数最终输出的结果是" paper vs scissor: Lose "。

用上述方法,就能避免 if else的书写和获取对象具体类型的方法

这种方法的精妙之处在于,通过调用 item1的compete方法,实现对item1的类型的分发,而在item1的compete方法中,用通过调用item2的eval方法,将自身this昨晚参数,实现了Item2中eval方法的分发

本文转载自:http://blog.csdn.net/sunmenggmail/article/details/10284071

刘小米_思聪
粉丝 58
博文 60
码字总数 43955
作品 0
西安
其他
私信 提问
加载中

评论(3)

oijava
oijava

引用来自“GoodLoser”的评论

写代码好奇怪
public Outcome compete(Item it) { return it.eval(this); } 你看这里,如果不做分发的话,你是不是得判断下it是什么类型呀?这么一倒腾,if else判断都不用了
oijava
oijava
哈哈 看了两边之后,明白了。赞一个。。。。是够巧妙的。79
麦壳原野
麦壳原野
写代码好奇怪
Java NIO 和 IO的区别

Java NIO 和 IO的区别 Java IO 中,ServerSocket 负责绑定 IP 地址,启动监听端口;Socket 负责发起连接操作,连接成功后,双方通过输入和输出流进行同步阻塞通信。采用 BIO 通信模型的 Serv...

秋风醉了
2014/11/01
341
0
Kafka与操作系统适配性研究

在《Apache Kafka实战》一书中,提到了操作系统与Kafka的适配性。涉及的的epoll与select问题,以及linux零拷贝技术较为重要,因此在此处将操作系统相关特性部分进行记录。 clients 底层网络库...

analanxingde
04/24
0
0
interview questions

1.java中为什么会出现多线程? Java内存模型决定了 CPU 不能 完全利用,为了充分利用CPU,所以产生了多线程技术。 2.多线程中,如果不调用start方法,直接调用run方法会发生什么? 只有调用T...

无断无灭无住无念
2017/11/06
26
0
JAVA NIO 和 AIO 的区别

Java NIO : 同步非阻塞,JVM实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 Java AIO(NIO.2) : ...

愚民日记
2015/05/11
3.6K
1
tomcat-tomcat bio nio apr 模式性能测试与个人看法

11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态、那后来主管就要求调优了,下面是tomcat bio、nio、apr模式以及后来自己测试的一些性能结果。 原理方面的资料都是从网上找...

抢地主
2017/11/04
124
0

没有更多内容

加载失败,请刷新页面

加载更多

计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
6
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
7
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
6
0
【技术分享】TestFlight测试的流程文档

上架基本需求资料 1、苹果开发者账号(如还没账号先申请-苹果开发者账号申请教程) 2、开发好的APP 通过本篇教程,可以学习到ios证书申请和打包ipa上传到appstoreconnect.apple.com进行TestF...

qtb999
昨天
10
0
再见 Spring Boot 1.X,Spring Boot 2.X 走向舞台中心

2019年8月6日,Spring 官方在其博客宣布,Spring Boot 1.x 停止维护,Spring Boot 1.x 生命周期正式结束。 其实早在2018年7月30号,Spring 官方就已经在博客进行过预告,Spring Boot 1.X 将维...

Java技术剑
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部