This is a design question better explained with a Stack Overflow analogy:
Users can earn Badges. Users, Badges and Earned Badges are stored in the database. A Badge’s logic is run by a Badge Condition Strategy. I would prefer not to have to store Badge Condition Strategies in the database, because they are complex tree structure objects.
How do I associate a Badge stored in the database with its Badge Condition Strategy? I can only think of workaround solutions. For example: create 1 class per badge and use a SINGLE_TABLE inheritance strategy开发者_运维知识库. Or get the badge from the database, and then programmatically lookup and inject the correct Badge Condition Strategy.
Thanks for suggesting a better design.
I don't see why you should store a strategy in DB - strategy is mostly expressed in code (possibly with some configuration parameters which, in turn, can be stored in DB, but that is a different issue to me).
OTOH I would keep the Badge and its condition strategy in one class, which eliminates your lookup problem. In Java, a good domain model would be to represent badges as an enum, with an overridable method to determine whether a given user has earned that specific badge.
Update here is an example:
enum Badge {
EPIC() {
public boolean isEligible(User user) {
// determine whether this user is eligible for the Epic badge
}
},
CRITIC() {
public boolean isEligible(User user) {
// determine whether this user is eligible for the Critic badge
}
},
...
;
public abstract boolean isEligible(User user);
}
But if you really want them separated, then in the constructor of e.g. LegendaryBadge
you say this.strategy = new LegendaryBadgeConditionStrategy();
How about a BadgeType enum with types that correspond to the Badges in the database? The enum can have a getBadgeConditionStrategy() method that returns the correct strategy for each enum value:
public enum BadgeType {
SMARTNESS( new SmartnessBadgeConditionStrategy() ),
WISDOM( new WisdomBadgeConditionStrategy(),
...;
private BadgeConditionStrategy badgeConditionStrategy;
BadgeType(BadgeConditionStrategy badgeConditionStrategy) {
this.badgeConditionStrategy = badgeConditionStrategy;
}
public getBadgeConditionStrategy() {
return badgeConditionStrategy;
}
}
精彩评论