ฉันทำงานเกี่ยวกับการรีแฟคเตอร์โค้ดบางส่วนและฉันคิดว่าฉันอาจทำขั้นตอนแรกลงไปในช่องกระต่าย ฉันเขียนตัวอย่างใน 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
ว่าแสดงรายละเอียดการต่อสู้บางอย่างสำหรับเกม (hitpoints, โจมตี, การป้องกัน) อย่างไรก็ตามสถิติ "ที่มีประสิทธิภาพ" หรือสถิติที่แท้จริงนั้นเป็นผลมาจากสถิติพื้นฐานที่ไม่สามารถเปลี่ยนแปลงได้และสถิติที่ผ่านการฝึกอบรมซึ่งสามารถเพิ่มขึ้นได้ ทั้งสองเกี่ยวข้องกันโดย
/**
* 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);
}
แต่พวกมันจะไม่เพิ่มขึ้นหลังจากการต่อสู้ การใช้ไอเท็มบางอย่างใช้กลยุทธ์บางอย่างการใช้สนามรบอย่างชาญฉลาดสามารถให้ประสบการณ์ที่แตกต่าง
ตอนนี้สำหรับคำถามของฉัน:
- มีชื่อสำหรับการแยกส่วนติดต่อโดย accessors และ mutators เป็นส่วนต่อประสานที่แยกกันหรือไม่?
- การแยกพวกเขาด้วยวิธีนี้ 'ถูกต้อง' หากพวกเขามีแนวโน้มที่จะใช้เท่ากันหรือมีรูปแบบที่แตกต่างและเป็นที่ยอมรับมากกว่าที่ฉันควรใช้แทน (เช่น
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);
}
}