Niminim
Niminim

Reputation: 678

Object-Oriented design - how important is encapsulation when there're lots of data-fields in one class?

I've a question regarding encapsulation:

Is it recommended to use encapsulation when a class has lots of data-fields?

Using the following class as an example:

abstract public class Character {
    private String name;
    private String characterClass;
    private int level;
    private int hitDice;

    private int strength;
    private int constitution;
    private int dexterity;
    private int intelligence;
    private int wisdom;
    private int charisma;

    private int hp;
    private int currentHp;
    private int armorClass;
    private int BaseAttackBonus;

    private long xp;
    private double gp;

    private Inventory inventory;
    private double carriedWeight;

    private Equipment equipment;

    protected Character(String name) {

        setName(name);
        setCharacterClass("Class");
        setLevel(1);
        setHitDice(0);

        setStrength(10);
        setConstitution(10);
        setDexterity(10);
        setIntelligence(10);
        setWisdom(10);
        setCharisma(10);

        setHp((int) getLevel() * (getHitDice() + getModifier(getConstitution())));
        setCurrentHp(getHp());
        setArmorClass(10 + getModifier(getDexterity()));
        setBaseAttackBonus(0);

        inventory = new Inventory();
        setCarriedWeight(0);

        equipment = new Equipment();

        setXp(0);
        setGp(20);

    }

    protected Character(String name, int lvl) {

        setName(name);
        setCharacterClass("Class");
        setLevel(lvl);
        setHitDice(0);

        setStrength(10);
        setConstitution(10);
        setDexterity(10);
        setIntelligence(10);
        setWisdom(10);
        setCharisma(10);

        setHp((int) getLevel() * (getHitDice() + getModifier(getConstitution())));
        setCurrentHp(getHp());
        setArmorClass(10 + getModifier(getDexterity()));
        setBaseAttackBonus(0);

        inventory = new Inventory();
        setCarriedWeight(0);

        equipment = new Equipment();

        setXp(1000 * (getLevel() - 1));
        setGp(getLevel() * 20);

    }

    void displayCharacter() throws IOException {
        System.out.print("\n\n");
        System.out.println("Name: " + getName());
        System.out.println("Class: " + getCharacterClass());
        System.out.println("Level: " + getLevel());
        System.out.println("HP: " + getHp());
        System.out.println("Current HP: " + getCurrentHp());
        System.out.println("Armor Class: " + getArmorClass());
        System.out.println("Base Attack Bonus : +" + getBaseAttackBonus());

        System.out.println("***************");
        System.out.println("Attributes: ");
        System.out.println("Strength: " + getStrength());
        System.out.println("Constitution: " + getConstitution());
        System.out.println("Dexterity: " + getDexterity());
        System.out.println("Intelligence: " + getIntelligence());
        System.out.println("Wisdom: " + getWisdom());
        System.out.println("Charisma: " + getCharisma());
        System.out.println("***************");
        equipment.showEquipment();
        inventory.showInventory();
        System.out.println("Carried weight: " + getCarriedWeight());

        System.out.println("");
        System.out.println("XP: " + getXp());
        System.out.println("Gold: " + getGp());
        System.out.println("");

    }

    public int getModifier(int number) {
        int mod = (int) ((number - 10) / 2);
        return mod;
    }

    public String getName() {
        return name;
    }

    public String getCharacterClass() {
        return characterClass;
    }

    public int getLevel() {
        return level;
    }

    public int getHitDice() {
        return hitDice;
    }

    public int getStrength() {
        return strength;
    }

    public int getConstitution() {
        return constitution;
    }

    public int getDexterity() {
        return dexterity;
    }

    public int getIntelligence() {
        return intelligence;
    }

    public int getWisdom() {
        return wisdom;
    }

    public int getCharisma() {
        return charisma;
    }

    public int getHp() {
        return hp;
    }

    public int getCurrentHp() {
        return currentHp;
    }

    public int getArmorClass() {
        return armorClass;
    }

    public int getBaseAttackBonus() {
        return BaseAttackBonus;
    }

    public Equipment getEquipment() {
        return equipment;
    }

    public Inventory getInventory() {
        return inventory;
    }

    public double getCarriedWeight() {
        return carriedWeight;
    }

    public long getXp() {
        return xp;
    }

    public double getGp() {
        return gp;
    }

    protected void setName(String Name) {
        name = Name;
    }

    protected void setCharacterClass(String characterClass) {
        this.characterClass = characterClass;
    }

    protected void setLevel(int lvl) {
        level = lvl;
    }

    protected void setHitDice(int hd) {
        hitDice = hd;
    }

    protected void setStrength(int str) {
        strength = str;
    }

    protected void setConstitution(int con) {
        constitution = con;
    }

    protected void setDexterity(int dex) {
        dexterity = dex;
    }

    protected void setIntelligence(int intel) {
        intelligence = intel;
    }

    protected void setWisdom(int wis) {
        wisdom = wis;
    }

    protected void setCharisma(int cha) {
        charisma = cha;
    }

    protected void setHp(int hitPoints) {
        hp = hitPoints;
    }

    protected void setCurrentHp(int curHp) {
        currentHp = curHp;
    }

    protected void setArmorClass(int ac) {
        armorClass = ac;
    }

    protected void setBaseAttackBonus(int bab) {
        BaseAttackBonus = bab;
    }

    protected void setXp(int XP) {
        xp = XP;
    }

    protected void setGp(double GP) {
        gp = GP;
    }

    protected void setCarriedWeight(double weight) {
        carriedWeight = weight;
    }

    public void attack(Character target) {

        try {
            ((Weapon) getEquipment().getPrimaryHand()).attack(this, target);
        } catch (NullPointerException e) {
            getEquipment().equipPrimaryHand(
                    MeleeWeapon.meleeWeaponList.get(0)); /* equip fist weapon */
            ((Weapon) getEquipment().getPrimaryHand()).attack(this, target);

            if (target.getCurrentHp() <= 0) {
                System.out.println(target.getName() + " is down !");
            }
        }
    }

    public void equip() {
        getInventory().equip(this);
    }

    public void addToInventory(Item newItem) {
        getInventory().addToInventory(this, newItem);
    }

}

Would storing most of the data-fields in different classes, such as strength and constitution in a Stats class, be considered as a better design?

Upvotes: 5

Views: 414

Answers (2)

Vince
Vince

Reputation: 15156

I think you're referring to decomposition - the act of breaking large systems down into smaller, easier to understand parts.

To properly decompose your code, you must focus on cohesion: How many things does your class represent? How well do they "stick" together?

Your class currently represents quite a few things:

  1. Character identity info, such as name
  2. Skill Tracker, such as constition
  3. Experience Tracker
  4. Inventory
  5. Personal Scale

Your 1 class represents multiple entities; it has low cohesion.


So to answer your question, yes, moving stat related fields to a stat class would be a good thing. But it's not just the fields you should move, it's the entire responsibility. This means if you have a resetStats() method, it too would go to the Stat class.

Decomposition helps further encapsulation if the members being moved are private, since it further hides info. But decomposition is it's own subject.

Upvotes: 4

Will Hartung
Will Hartung

Reputation: 118714

Objects have behavior. State within the object is there to support that behavior. Separating out a bunch of state, simply as a container of state, rather than a distinct object with their own specific behaviors, doesn't make a lot of sense in the big picture of things.

Upvotes: 2

Related Questions