我一直在进行一些代码的重构,我想我可能已经迈出了第一步。我正在用Java编写示例,但我想它可能是不可知的。
我有一个Foo
定义为的接口
public interface Foo {
int getX();
int getY();
int getZ();
}
和一个实现
public final class DefaultFoo implements Foo {
public DefaultFoo(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
private final int x;
private final int y;
private final int z;
}
我还有一个接口MutableFoo
,可提供匹配的变异子
/**
* This class extends Foo, because a 'write-only' instance should not
* be possible and a bit counter-intuitive.
*/
public interface MutableFoo extends Foo {
void setX(int newX);
void setY(int newY);
void setZ(int newZ);
}
MutableFoo
可能存在两种实现方式(我尚未实现它们)。其中之一是
public final class DefaultMutableFoo implements MutableFoo {
/**
* A DefaultMutableFoo is not conceptually constructed
* without all values being set.
*/
public DefaultMutableFoo(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public void setX(int newX) {
this.x = newX;
}
public int getY() {
return y;
}
public void setY(int newY) {
this.y = newY;
}
public int getZ() {
return z;
}
public void setZ(int newZ) {
this.z = newZ;
}
private int x;
private int y;
private int z;
}
我之所以将它们分开,是因为每个人使用它的可能性相同。这意味着,使用这些类的某人也很可能想要一个不可变的实例,因为他们想要一个可变的实例。
我拥有的主要用例是一个名为接口的接口StatSet
,它代表游戏的某些战斗细节(命中率,攻击,防御)。但是,“有效”统计数据或实际统计数据是基础统计数据(不能更改)和受训练统计数据(可以增加)的结果。这两个是由
/**
* The EffectiveStats can never be modified independently of either the baseStats
* or trained stats. As such, this StatSet must never provide mutators.
*/
public StatSet calculateEffectiveStats() {
int effectiveHitpoints =
baseStats.getHitpoints() + (trainedStats.getHitpoints() / 4);
int effectiveAttack =
baseStats.getAttack() + (trainedStats.getAttack() / 4);
int effectiveDefense =
baseStats.getDefense() + (trainedStats.getDefense() / 4);
return StatSetFactory.createImmutableStatSet(effectiveHitpoints, effectiveAttack, effectiveDefense);
}
每次战斗后,训练有素的统计数据都会增加
public void grantExperience() {
int hitpointsReward = 0;
int attackReward = 0;
int defenseReward = 0;
final StatSet enemyStats = enemy.getEffectiveStats();
final StatSet currentStats = player.getEffectiveStats();
if (enemyStats.getHitpoints() >= currentStats.getHitpoints()) {
hitpointsReward++;
}
if (enemyStats.getAttack() >= currentStats.getAttack()) {
attackReward++;
}
if (enemyStats.getDefense() >= currentStats.getDefense()) {
defenseReward++;
}
final MutableStatSet trainedStats = player.getTrainedStats();
trainedStats.increaseHitpoints(hitpointsReward);
trainedStats.increaseAttack(attackReward);
trainedStats.increaseDefense(defenseReward);
}
但战斗结束后并没有增加。使用某些物品,使用某些战术,巧妙地使用战场都可以带来不同的体验。
现在我的问题是:
- 是否有用于按访问者和更改者将接口拆分为单独接口的名称?
- 如果以同样的方式使用它们,或者是否存在我应该使用的其他更可接受的模式(例如
Foo foo = FooFactory.createImmutableFoo();
,可能返回DefaultFoo
或DefaultMutableFoo
由于createImmutableFoo
返回而被隐藏Foo
)则以这种方式拆分它们是“正确”的方法吗? - 除了使接口层次结构复杂化之外,使用此模式是否有立即可预见的缺点?
之所以开始设计这种方式,是因为我的想法是,接口的所有实现者都应遵循最简单的接口,并且仅提供其他功能。通过向接口添加设置器,现在可以独立于其部分修改有效统计信息。
为新建一个类EffectiveStatSet
没有多大意义,因为我们不会以任何方式扩展功能。我们可以更改实现,并将EffectiveStatSet
两种不同的方法组合在一起StatSets
,但是我认为这不是正确的解决方案。
public class EffectiveStatSet implements StatSet {
public EffectiveStatSet(StatSet baseStats, StatSet trainedStats) {
// ...
}
public int getHitpoints() {
return baseStats.getHitpoints() + (trainedStats.getHitpoints() / 4);
}
}