作者Killercat (杀人猫™)
看板java
标题Re: [问题] is-a 关系在Java程式的时候的用意?
时间Thu Aug 1 11:39:53 2013
※ 引述《SamLucien (黑)》之铭言:
: 我用Java SE技术手册 良葛格 这本想提问题
: (第六章 6-7页)
: 一个游戏 脚色(Role)类别
: 剑士(SwordsMan)、魔法师(Magician) 则是继承了 Role类别的所有基本脚色该有的东西
: 也就是 SwordsMan is-a Role , Magician is-a Role
: 通常在Java 看到的实作剑士(SwordsMan)、魔法师(Magician)
: 通常都会这样写:(1)
: SwordsMan role1 = new SwordsMan();
: Magician role2 = new Magician();
: 但是,通常也会看到这样写:(2)
: Role role1 = new SwordsMan();
: Role role2 = new Magician();
: 我想请问的是这两种写法有什麽差别?
: 因为现在遇到看不懂的地方也包含
: 就我的认知是应该这样写
: ArrayList<Map<String,Object>> list
: = new ArrayList<Map<String,Object>>();
: 但是看到这 就不知道为什麽 可以这样写 用意何在?
: List<Map<String,Object>> list
: = new ArrayList<Map<String,Object>>();
: 就是想问说(1)与(2) 这样的写法 有什麽差别呢???
: (2) 的写法有什麽用意???
: 谢谢大家~
不过现在的主流做法并不是继承class。
继承class(後面会提到扩展interface)一定是正确的,但是现在基本上已经不流行这套
因为它会造成一些问题,尤其是java并不允许多重继承,会造成很多设计上的困难
我先举个例子,我们传统的写法可能会写成这样
interface IRole {
int getHP();
int getMP();
int getEXP();
}
class Role implements IRole {
int HP;
int MP;
int EXP;
bool kill(IRole target);
bool kiss(IRole target);
bool kick(IRole target);
}
class Swordman extends RoleBase {
bool somethingSwordmanOnly(IRole target);
}
IRole a = new Swordman();
IRole b = new Magician();
可能差一点的coder连IRole那层都没有, 直接就
Role a = new Swordman();
whatever,这是举例,大家都知道的
现在的主流分为以下几种
1. 继承interface而非class
interface IRole {
int getHP();
int getMP();
int getEXP();
boolean kill(IRole target);
boolean kiss(IRole target);
boolean kick(IRole target);
}
interface ISwordman extends IRole {
int getSomethingSwordmanOnly();
boolean doSomethingSwordmanOnly(IRole target);
}
class Swordman implements ISwordman {
}
这样做有几个好处,首先最显而易见的好处就是Swordman避开了继承的问题
改成实作。继承只能继承一个,但实作可以实作很多很多个
用法也完全一样
IRole role = new Swordman();
但是这样也是有缺点的:你可以想像终端class(也就是最後implements的class)
会有多肥大 =P 而且...
2. 使用inner implementation
interface IRoleStat {
//getHP, MP, EXP...同上
}
interface IAction {
//角色共通的行为, 比方说target(), kill(), attack()....etc
}
interface ISwordmanStat extends IRoleStat {
//定义Swordman才有的property
}
interface ISwordmanAction extends IAction {
}
class Role {
IRoleStat charStat;
IAction charAction;
}
可能当你想创造一个战士的时候
Role role = new Role(new SwordmanStat(), new SwordmanAction());...
当然,大家都懂design pattern,这个可以用Factory来做 XD
这样做还有一个好处,比方说有个敌人特色是会分身,HP会共享
Role enemy = context.getEnemy();
分身後
Role doppelganger = new Enemy();
doppelganger.setCharStat(enemy.getCharStat());
现在不管你打谁两边血量都会一起扣了,连delegate都不用 XD
这只是刚好游戏可以拿这个当例子啦...
3. 很类似2 但是把所有东西转成JSON(或者任何你能解析的格式)
class Role {
String actionProperty;
String statProperty;
}
这种写法其实出乎意料的多专案使用(不管java, ios...)
他的相依性是最低的,甚至有人替他写出高效能的property实作
class Role {
SuperRockProperty actionProperty;
SuperRockProperty statProperty;
}
缺点当然明显,就是没有形别安全根检查。不过会这样写的大概也不在乎这个了...
更狠一点的话会变成这样
class Role {
SuperRockProperty property;
}
连分类都省了....
除了继承以外,我相信1 2都是可以参考的新的实作风法。
Spring也有类似DI等等的低相依class injection方法,这些也可以参考一下
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 59.124.251.135
1F:推 PsMonkey:一开始的 IRole 少了 abstract? 08/01 11:52
2F:→ PsMonkey:还是你写得根本不是 Java(bool????) 08/01 11:52
改一下你说的部分
不过IRole本来就不用abstract阿 他是interface XD
一个常常得写四种语言的人 bool boolean不分是很合理地(快逃)
※ 编辑: Killercat 来自: 59.124.251.135 (08/01 11:59)
3F:→ Killercat:噢你说的abstract指的是没function 那只是懒得写getter 08/01 12:00
不过想了一想PS猴说得有道理 还是补上去好了....
※ 编辑: Killercat 来自: 59.124.251.135 (08/01 12:17)
※ 编辑: Killercat 来自: 59.124.251.135 (08/01 13:11)
4F:推 PsMonkey:没内容的 method 没有 abstract 修饰感觉很奇怪阿 Orz 08/01 13:28
5F:推 popcorny:有点overengineering..有时候架构够用就好 不要太复杂 08/01 13:34
6F:→ Killercat:这算是我目前看过常见的实作法 而非要这样设计 08/01 13:35
7F:推 popcorny:1像是bridge pattern, 2像是delegate pattern.. 08/01 13:44
8F:→ Killercat:其实这些概念统称composite :) 08/01 13:59
9F:→ Killercat:另外3的概念其实就是javascript来的... 我觉得颇畸形 08/01 14:01