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