好的,我说我正在为以下足球俱乐部建模: 所有人都是个人。 玩家是一个人,因此扩展个人。 会员是个人,因此会扩展个人。
超类:
Individual {name, eyeColour}
子类:
Player extends Individual {position}
Member extends Individual {subscription}
汤姆是足球俱乐部的老板:
Individual i = new Individual("Tom", "Blue")
Bob&托尼是球员:
Player p1 = new Player("Bob", "Green", "Goalkeeper")
Player p2 = new Player("Tony", "Blue", "Striker")
史蒂夫是会员:
Member m = new Member("Steve", "Brown", 5.00)
个人,玩家和会员都使用Objectify持久保存到GAE数据存储中的同一种(个人)。
name eyeColour position subscription ^d Tom Blue [missing] [missing] Individual Bob Green Goalkeeper [missing] Player Tony Blue Striker [missing] Player Steve Brown [missing] 5.00 Member
如果是,例如Bob决定成为会员还是玩家?我想存储是订阅。 我无法将鲍勃贬低为个人,然后向成员倾斜。 Java不允许这样做。 我无法创建新成员并复制Bob的Player对象的所有属性并将其存储回相同的ID - 我将失去他的Position属性。 我需要Bob成为数据库中的成员和播放器,但不是对象形式(我不是在多重继承之后) 我仍然想得到(Player.class,“Bob”)并拥有一个Player对象或get(Member.class,“Bob”)并拥有一个Member对象。 我不需要同时具有位置和订阅属性的Object。
我也想避免这是数据存储区:
name eyeColour position subscription ^d Tom Blue [missing] [missing] Individual Bob Green Goalkeeper [missing] Player Bob Green [missing] 10.00 Member Tony Blue Striker [missing] Player Steve Brown [missing] 5.00 Member
因为Bob现在在名称和eyeColour上存在数据重复,这可能会导致数据不一致。
有关如何建模的任何想法?
如果汤姆成为一名球员,或史蒂夫成为会员,该怎么办?
答案 0 :(得分:5)
Individual {name, eyeColour}
MemberRole {individual, position}
PlayerRole {individual, subscription}
很明显,继承不适合您的任务。例如,某人可以在两个不同的球队中比赛,或者是两个不同俱乐部的成员(并且您的原始结构不会允许拥有多个足球俱乐部)。
个人是什么,他们有什么角色,是不同的事情。例如,您不希望某个全局数据库在同一Individual
表中存储您的姓名,您的堆栈溢出点,您的婚姻状况和您的职业。
如果鲍勃决定成为会员,鲍勃本身并没有改变;它的角色呢。鲍勃决定成为一名成员仍然是同样优秀的老鲍勃,只是他现在能够做一些他早些时候被禁止的事情。
PS:您在答案中使用了订阅一词。这就是播放器的内容 - 订阅。 Subscription
显然不是Individual
s的某个特定子集,Subscription
是完全不同的实体。当然,它应该知道它属于哪个Individual
,但它本身不是Individual
。
答案 1 :(得分:3)
首先,我会将所有人视为Individual
,但您希望将某些人设为Player
或Member
或both
。
您需要使用Interfaces
对此方案进行建模。由于我不是Java,我建议做类似于这段代码的事情:
interface IPlayable {void MakePlayable (string position)};
interface IMembership {void AddMembership (double subscription)};
class Individual implements IPlayable, IMembership{name, eyeColour, IPlayable.MakePlayable(string position), IMembership.AddMembership(double subscription)};
//Usage to make Tom a Player
Individual tom = new Individual("Tom", "Blue");
tom.MakePlayable("GoalKeeper");
//Usage to make Steve a Member
Individual steve = new Individual("Steve", "Brown");
steve.AddMembership(5.00);
//Usage to make Jim both a Player and a Member
Individual jim = new Individual("Jim", "Black");
jim.MakePlayable("Forward");
jim.AddMembership(4.00);
除了实现多个接口场景外,使用 这里也需要接口,因为使用Member类会 否则使个人成为某个俱乐部的常任成员,使用 IMembership界面,您可以添加
RemoveMembership()
方法 有助于在需要时删除Individual
的成员资格 将来。
答案 2 :(得分:0)
试试这个......
个人是 SuperClass 。
播放器和会员 接口。
假设Bob是玩家,也是会员。
现在..
Bob是个人(即扩展个人)
Bob 实施播放器和会员接口(即Bob播放播放器和会员的角色)
答案 3 :(得分:0)
请参阅GAE文档中的Entity Relationships in JDO:
您可以使用字段来建模持久对象之间的关系 对象类型。持久对象之间的关系可以是 描述为拥有,其中一个对象不能没有 其他或无主的,两个对象可以独立存在 彼此的关系。 App Engine的实现 JDO接口可以对拥有的和无主的一对一建模 关系和一对多关系,单向和 双向的。
我说你有两个“拥有”的关系。 Player
和Member
都“拥有”Individual
。
答案 4 :(得分:0)
public class Individual {
Role role;
int position; //empty for MEMBER,filled for PLAYER_MEMBER and PLAYER
int subscription; //empty for PLAYER,filled for PLAYER_MEMBER and MEMBER }
public enum Role { MEMBER,PLAYER,PLAYER_MEMBER; }
因此,当切换完成后,您只需更改角色并完成缺少的字段。 应该考虑验证。
答案 5 :(得分:0)
创建一个Indiviual类(名称,eyecolor)并创建Owner,Player和Member的接口。您将拥有独特的个人,并继续为他们添加功能。因此,您将拥有所需的表,最后一列将列出不同的实现。
使用接口要比实现多继承好得多,而java就是这样做的。所以,你最好使用这个