나는 코드를 리팩토링하는 일을하고 있었고, 토끼 구멍에서 첫 단계를 밟은 것 같다. 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);
}
}