Get instance from other classes

Discussion in 'Spigot Plugin Development' started by MaTaMoR_, May 2, 2015.

  1. So im developing a minigame plugin and it have a lot of classes but i want to know how i should get the instance from the classes
     
    • Funny Funny x 1
    • Optimistic Optimistic x 1
  2. Inkzzz

    Resource Staff

    Do you mean something like this?

    Code (Text):
        static Main instance;

        public static Main getInstance() {
            return instance;
        }

        static API api;

        public API getAPI() {
            return api;
        }

        public void onEnable() {
            instance = this;
            api = new API();
             }
     
    • Optimistic Optimistic x 1
  3. Until know i used that but i saw some post where says use singletons is bad .
     
  4. gigosaurus

    Supporter

    Singletons are not necessarily bad but they are normally overused by people who don't completely understand OOP.
     
  5. So what can i do¿? I have so many classes to acces
     
  6. gigosaurus

    Supporter

    Without seeing your code and what you're actually trying to do and what each class actually consists of, it's hard to answer that question without making a fair few assumptions.
     
  7. So i have a class called "Arena", "ArenaManager" and "ArenaEngine" in other package "Tag", "TagManager", and "TagEngine" in other package "Gui", "GuiManager" and "GuiEngine" and some more packages like these.
     
  8. gigosaurus

    Supporter

    What classes does each class need to access? What do the Engine classes do?
    It sounds like you should be storing instance(s) of each data class in the Manager, and then have a reference to each Manager (or possibly Engine) from the main plugin class so that you can access each manager (or engine) from it.
     
    #8 gigosaurus, May 2, 2015
    Last edited: May 2, 2015
  9. JamesJ

    Supporter

    Code (Text):

    private static MainClass instance;
    private Engine engine;

    public void onEnable(){
        instance = this;
        engine = new Engine();
    }

    public static MainClass getInstance(){ return instance;}

    public Engine getEngine(){ return Engine; }
     
    Wrote that one my phone, probably a few errors. You can try using something like that.
     
    • Like Like x 1
  10. Read the whole post before post.
     
  11. gigosaurus

    Supporter

    Actually he provided something similar to what I explained.
     
  12. Probably personal preference, and IMO it's cleaner than static. I like passing the plugin class via a constructor.
     
    • Agree Agree x 1
  13. "Until know i used that but i saw some post where says use singletons is bad ."

    One of my packages:
    Tag:
    Code (Text):

    @SerializableAs("Tag")
    public class Tag implements ConfigurationSerializable {

    private static final Map<String, Tag> Tags = new HashMap<>();
    public static Map<String, Tag> getTags() {
        return Tags;
    }

    private final String name;
    private String prefix, suffix;
    private String permission;
    private int rank;
    private final Team team;

    public Tag(String name, String prefix, String suffix, String permission, int rank) {
        this.name = name;
        this.prefix = prefix;
        this.suffix = suffix;
        this.permission = permission;
        this.rank = rank;
        this.team = QOMain.getInstance().getScoreboard().registerNewTeam(this.name);

        Tags.put(this.name, this);
    }

    public Tag(String name, Map<String, Object> map) {
        this.name = name;
        this.prefix = (String) map.get("Prefix");
        this.suffix = (String) map.get("Suffix");
        this.permission = (String) map.get("Permission");
        this.rank = (Integer) map.get("Rank");
        this.team = QOMain.getInstance().getScoreboard().registerNewTeam(this.name);

        Tags.put(this.name, this);
    }

    @Override
    public Map<String, Object> serialize() {
        Map<String, Object> map = new HashMap<>();
        map.put("Prefix", this.prefix);
        map.put("Suffix", this.suffix);
        map.put("Permission", this.permission);
        map.put("Rank", this.rank);

        return map;
    }

    public void setup() {
        if(this.prefix != null) {
            String prefixToSet = null;
            if(this.prefix.length() > 16) {
                prefixToSet = this.prefix.substring(0, 16);
            } else {
                prefixToSet = this.prefix;
            }
            this.team.setPrefix(Util.color(prefixToSet));
        }
        if(this.suffix != null) {
            String suffixToSet = null;
            if(this.suffix.length() > 16) {
                suffixToSet = this.suffix.substring(0, 16);
            } else {
                suffixToSet = this.suffix;
            }
            this.team.setSuffix(Util.color(suffixToSet));
        }
    }

    public String getName() {
        return this.name;
    }

    public String getPrefix() {
        return this.prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return this.suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public String getPermission() {
        return this.permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public Team getTeam() {
        return this.team;
    }

    public void removePlayer(UUID uuid) {
        this.team.removePlayer(Bukkit.getOfflinePlayer(uuid));
    }

    public void addPlayer(UUID uuid) {
        this.team.addPlayer(Bukkit.getOfflinePlayer(uuid));
    }

    public void removeTeam() {
        this.team.unregister();
    }

    public void save() {
        TagConfig.getInstance().set("Tags." + this.name, serialize());
    }

    public void unload() {
        save();
        removeTeam();
        Tags.remove(this.name);
    }

    public void remove() {
        removeTeam();
        Tags.remove(this.name);
    }
    }
     
    TagManager:
    Code (Text):

    public class TagManager {

    private static final TagManager tmanager = new TagManager();
    public static TagManager getInstance() {
        return tmanager;
    }

    public void loadTags() {
        if(!TagConfig.getInstance().contains("Tags")) {
            Tag tag = new Tag("Test", "Prefix ", " Suffix", "quarkoptions.tag.test", 999);
                tag.save();
        } else {
            for(String tagName : TagConfig.getInstance().<ConfigurationSection>get("Tags").getKeys(false)) {
                Tag tag = new Tag(tagName, TagConfig.getInstance().<ConfigurationSection>get("Tags." + tagName).getValues(true));
                    tag.setup();
                Bukkit.getLogger().log(Level.INFO, "[QuarkOptions] Tag {0} creado", tagName);
            }
        }
    }

    public void saveTags() {
        for(Tag tag : getTags()) {
            tag.save();
        }
    }

    public Tag[] getTags() {
        return Tag.getTags().values().toArray(new Tag[Tag.getTags().values().size()]);
    }

    public boolean exists(String tagName) {
        return Tag.getTags().containsKey(tagName);
    }

    public Tag getTag(Player player) {
        Tag playerTag = null;
        for(Tag tag : getTags()) {
            if(player.hasPermission(tag.getPermission())) {
                if(playerTag == null) {
                    playerTag = tag;
                } else {
                    if(tag.getRank() < playerTag.getRank()) {
                        playerTag = tag;
                    }
                }
            }
        }
        return playerTag;
    }

    public Tag getTag(String name) {
        return Tag.getTags().get(name);
    }

    public Tag getPlayerTag(Player player) {
        for(Tag tag : getTags()) {
            if(tag.getTeam().hasPlayer(player)) {
                return tag;
            }
        }
        return null;
    }

    public void removeTag(Player player) {
        Tag tag = getPlayerTag(player);
            tag.removePlayer(player.getUniqueId());
    }

    public void removeTags() {
        for(Tag tag : getTags()) {
            tag.remove();
        }
    }

    public void setTags() {
        for(Player online : Bukkit.getOnlinePlayers()) {
            if(online.getScoreboard() == null || !online.getScoreboard().equals(QOMain.getInstance().getScoreboard())) {
                online.setScoreboard(QOMain.getInstance().getScoreboard());
            }
            Tag tag = getPlayerTag(online);
            if(tag != null) {
                continue;
            }
                tag = getTag(online);
            if(tag == null) {
                continue;
            }
            tag.addPlayer(online.getUniqueId());
        }
    }

    public void move(Player player, Tag tag) {
        Tag actualTag = getPlayerTag(player);

        if(actualTag != null) {
            actualTag.removePlayer(player.getUniqueId());
        }

        tag.addPlayer(player.getUniqueId());
    }

    public void reloadTags() {
        removeTags();
        TagConfig.getInstance().setup();
        loadTags();
        setTags();
    }
    }
     
    Tag engine:
    Code (Text):

    public class TagEngine implements Listener {

    private static final TagEngine tengine = new TagEngine();
    public static TagEngine getInstance() {
        return tengine;
    }

    @EventHandler(priority = EventPriority.NORMAL)
    public void setTag(PlayerJoinEvent event) {
        Player player = event.getPlayer();
               player.setScoreboard(QOMain.getInstance().getScoreboard());
         
        Tag tag = TagManager.getInstance().getTag(player);
        if(tag == null) {
            return;
        }

        tag.addPlayer(player.getUniqueId());
    }

    @EventHandler(priority = EventPriority.NORMAL)
    public void removeTag(PlayerQuitEvent event) {
        Player player = event.getPlayer();

        Tag tag = TagManager.getInstance().getPlayerTag(player);
        if(tag == null) {
            return;
        }

        tag.removePlayer(player.getUniqueId());
    }
    }
     
    Tag config:
    Code (Text):

    public class TagConfig {

    private TagConfig() { }

    private static final TagConfig instance = new TagConfig();
    public static TagConfig getInstance() {
            return instance;
    }

    private File file;
    private FileConfiguration config;

    public void setup() {
        file = new File(QOMain.getInstance().getDataFolder(), "tags.yml");

        if (!file.exists()) {
                try { file.createNewFile(); }
                catch (Exception e) {}
        }

        config = YamlConfiguration.loadConfiguration(file);
    }

    public void set(String path, Object value) {
        config.set(path, value);
        save();
    }

    public ConfigurationSection createConfigurationSection(String path) {
        ConfigurationSection cs = config.createSection(path);
        save();
        return cs;
    }

    @SuppressWarnings("unchecked")
    public <T> T get(String path) {
        return (T) config.get(path);
    }

    public boolean contains(String path) {
        return config.contains(path);
    }

    public void save() {
        try { config.save(file); }
        catch (Exception e) {}
    }
    }
     

    Do you mean something like this ? :
    Code (Text):

    public class SecondaryClass {
    private final MainClass plugin;
    public SecondaryClass(MainClass i) {
       plugin = i;
    }
     
    If you meant this, i used it but in class like Tag i can't use it.

    So i really need to know which option is the best, because i'm developing other plugin which is used for lobby plugin by a server with +500 players so it must be really efficient
     
    #13 MaTaMoR_, May 2, 2015
    Last edited: May 3, 2015
  14. gigosaurus

    Supporter

    EDIT: revised what I originally put.

    This is what I would do. Remember that this isn't the only solution.

    Move the Tags map in the Tag class into your TagManager class. Your TagManager class manages the tags so it makes more sense if it stores them.
    Move tmanager in TagManager to your plugin class.
    Move tengine in TagEngine to your TagManager class.
    Move tconfig in TagConfig to your TagManager class.

    Getting a tag like you have in TagEngine would now be done like this:
    Code (Java):
    Tag tag = MainClass.getInstance().getTagManager().getPlayerTag(player);
     
    #14 gigosaurus, May 3, 2015
    Last edited: May 3, 2015
    • Agree Agree x 1
  15. Terrible idea. What's the point of a manager if you're just going to manage it with the main class?
     
  16. I really have to do that for all classes ? Look at this isn't even all classes, and that will look so bad, main class will have over 2000 lines of code, so many things, i don't think it is a good idea.

    Edit: @1Rogue -sensei help us
     
  17. gigosaurus

    Supporter

    I only suggested storing the manager in the main class because the plugin essentially owns that instance of the manager, so it makes sense for it to be there. Otherwise you'll just have singleton classes all over the place.

    Let me revise what I originally put. I think storing the engine inside the manager would make more sense.

    You will only need to store the managers in the main class. All the utils classes will probably be filled with static methods and so won't require an instance. The engine, config and data classes will be in its respective manager.

    Of course the other option is to keep your managers as singletons, but still have the engine and other classes stored inside it.
     
  18. Right, but you don't need to store the instances of other things related to teams, when there's a TeamManager. It defeats the purpose.
    Generally your plugin structure is similar to a tree data structure, you have the main class as the "root" class, and you have references to managers/handlers etc which in turn control references in a similar manner. By passing around your main class, you always have a way to make references to every other part of the plugin.
     
  19. gigosaurus

    Supporter

    Yeah, I overlooked that on my initial reply and revised it in my previous post.
     
  20. WTF to this whole thread..

    How can you really screw up here.. There's basically two ways to do it.

    Either store the INSTANCE in the class as static, or pass it via a constructor. Either way they both work.

    The only reason I prefer the latter is because there's a less chance of NPE's.
     
    • Optimistic Optimistic x 1