0

I try to program a text adventure from scratch and I am currently working on save and load functions. I am using JAXB to store every object in a separate XML file.

Since I am handling a lot of different types, I have to create two new functions for each type, resulting in lots of duplicated code.

Is there a way to simplify this? (Most classes share a common super-class, ex. Consumable, Wearable, Weapon, Misc extend Item.)

Or is it better to keep the fully functions separated?

UPDATE: I managed to simplify the save and load functions in Actor Manager. Actor is the super-class and Humanoid and Creature are its sub-classes.

Is it save to do it this way?

But it is not working for ItemManager.

public class ItemManager {

    // Constructor Singleton Pattern
    private ItemManager() { }

    private static class ItemManagerHelper {
        private static final ItemManager INSTANCE = new ItemManager();
    }

    public static ItemManager getInstance() {
        return ItemManagerHelper.INSTANCE;
    }

    // Create
    public Consumable createConsumable(String name, int value, ConsumableType consumableType) throws JAXBException {
        Consumable consumable =
                new Consumable(dataManager.generateId(consumableType.getConsumableType()), name, value, consumableType);

        save(consumable);
        return consumable;
    }

    public Misc createMisc(String name, int value, MiscType miscType) throws JAXBException {
        Misc misc =
                new Misc(dataManager.generateId(miscType.getMiscType()), name, value, miscType);

        save(misc);
        return misc;
    }

    public Weapon createWeapon(String name, int value, WeaponType weaponType) throws JAXBException {
        Weapon weapon =
                new Weapon(dataManager.generateId(weaponType.getWeaponType()), name, value, weaponType);

        save(weapon);
        return weapon;
    }

    public Wearable createWearable(String name, int value, WearableType wearableType) throws JAXBException {
        Wearable wearable =
                new Wearable(dataManager.generateId(wearableType.getWearableType()), name, value, wearableType);

        save(wearable);
        return wearable;
    }

    // Save
    private void save(Consumable consumable) throws JAXBException {
        String type = consumable.getConsumableType().getConsumableType();
        File file = new File(dataManager.getTypePath(type) + consumable.getId() + ".xml");

        JAXBContext context = JAXBContext.newInstance(Consumable.class);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(consumable, file);
        marshaller.marshal(consumable, System.out);
    }

    private void save(Misc misc) throws JAXBException {
        String type = misc.getMiscType().getMiscType();
        File file = new File(dataManager.getTypePath(type) + misc.getId() + ".xml");

        JAXBContext context = JAXBContext.newInstance(Misc.class);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(misc, file);
        marshaller.marshal(misc, System.out);
    }

    private void save(Weapon weapon) throws JAXBException {
        String type = weapon.getWeaponType().getWeaponType();
        File file = new File(dataManager.getTypePath(type) + weapon.getId() + ".xml");

        JAXBContext context = JAXBContext.newInstance(Weapon.class);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(weapon, file);
        marshaller.marshal(weapon, System.out);
    }

    private void save(Wearable wearable) throws JAXBException {
        String type = wearable.getWearableType().getWearableType();
        File file = new File(dataManager.getTypePath(type) + wearable.getId() + ".xml");

        JAXBContext context = JAXBContext.newInstance(Wearable.class);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(wearable, file);
        marshaller.marshal(wearable, System.out);
    }

    // Load
    public Consumable loadConsumable(String idString) throws JAXBException {
        File file = new File(dataManager.getTypePath(DataManager.typeFromId(idString)) + idString + ".xml");

        JAXBContext jaxbContext = JAXBContext.newInstance(Consumable.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Consumable consumable = (Consumable) jaxbUnmarshaller.unmarshal(file);

        System.out.println(consumable);

        return consumable;
    }

    public Misc loadMisc(String idString) throws JAXBException {
        File file = new File(dataManager.getTypePath(DataManager.typeFromId(idString)) + idString + ".xml");

        JAXBContext jaxbContext = JAXBContext.newInstance(Misc.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Misc misc = (Misc) jaxbUnmarshaller.unmarshal(file);

        System.out.println(misc);

        return misc;
    }

    public Weapon loadWeapon(String idString) throws JAXBException {
        File file = new File(dataManager.getTypePath(DataManager.typeFromId(idString)) + idString + ".xml");

        JAXBContext jaxbContext = JAXBContext.newInstance(Weapon.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Weapon weapon = (Weapon) jaxbUnmarshaller.unmarshal(file);

        System.out.println(weapon);

        return weapon;
    }

    public Wearable loadWearable(String idString) throws JAXBException {
        File file = new File(dataManager.getTypePath(DataManager.typeFromId(idString)) + idString + ".xml");

        JAXBContext jaxbContext = JAXBContext.newInstance(Wearable.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Wearable wearable = (Wearable) jaxbUnmarshaller.unmarshal(file);

        System.out.println(wearable);

        return wearable;
    }

}

package Actor;

@SuppressWarnings("unused")
public class ActorManager {
    // Class Variables
    private DataManager dataManager = DataManager.getInstance();

    // Constructor Singleton Pattern
    private ActorManager() { }

    private static class ActorManagerHelper {
        private static final ActorManager INSTANCE = new ActorManager();
    }

    public static ActorManager getInstance() {
        return ActorManagerHelper.INSTANCE;
    }

    // Create
    public Humanoid createHumanoid(String name) throws JAXBException {
        Humanoid humanoid =
                new Humanoid(dataManager.generateId(ActorType.HUMANOID.getActorType()), ActorType.HUMANOID, name);

        saveActor(humanoid);
        return humanoid;
    }

    public Creature createCreature(String name) throws JAXBException {
        Creature creature =
                new Creature(dataManager.generateId(ActorType.CREATURE.getActorType()), ActorType.CREATURE, name);

        saveActor(creature);
        return creature;
    }

    // Save
    private void saveActor(Actor actor) throws JAXBException {
        File file = new File
                (dataManager.getTypePath(actor.getActorTypeString()) + actor.getId() + ".xml");

        JAXBContext context = JAXBContext.newInstance(Creature.class);

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(actor, file);
        marshaller.marshal(actor, System.out);
    }

    // Load
    private Actor loadActor(String id) throws JAXBException {
        File file = new File(dataManager.getTypePath(DataManager.typeFromId(id)) + id + ".xml");
        Actor actor;
        JAXBContext jaxbContext = JAXBContext.newInstance(Actor.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        switch(DataManager.typeFromId(id)) {
            case "humanoid":
                actor = (Humanoid) jaxbUnmarshaller.unmarshal(file);
                break;
            case "creature":
                actor = (Creature) jaxbUnmarshaller.unmarshal(file);
                break;
            default:
                System.out.println("ID is not of type Actor. Returning null.");
                actor = null;
        }

        return actor;
    }

    public Creature loadCreature(String id) throws JAXBException {
        return (Creature) loadActor(id);
    }

    public Humanoid loadHumanoid(String id) throws JAXBException {
        return (Humanoid) loadActor(id);

    }
    
}
  • Would you mind to add one to those types, such as Weapon Type, into your question? It seems that the first step would be to ensure these "Types" share the same Interface. In this way, you could have all of them using the same method such as `getType()` instead of having something like `getWeaponType()`. This could simplify your code into a better pattern such as Factory or Factory Method. – acarlstein Aug 04 '20 at 15:50
  • Check this solution on how to make the method return type generic: https://stackoverflow.com/questions/450807/how-do-i-make-the-method-return-type-generic – acarlstein Aug 04 '20 at 16:06
  • Thanks for the answer I am trying to implement the interface. - "Would you mind to add one to those types, such as Weapon Type, into your question?" Handling multiple Object Types (ex. Weapon, Consumable... ) ... Do you mean like that? –  Aug 04 '20 at 16:13
  • take a look into the link I send you about return type generic. You could either use a super-class for all your classes or you could use an interface which would allow later your classes to extend a superclass if you need it. – acarlstein Aug 04 '20 at 17:58

0 Answers0