简体   繁体   中英

Am I abusing static?

To disguise players as another Entity, I made a disguise class as you can see here:

public class Disguise
{
    private static HashSet<Disguise> disguises = new HashSet<>();
    private net.minecraft.server.v1_8_R2.EntityLiving nmsEntity;
    private Player disguise;

    public Disguise(Player disguise, EntityLiving entity, boolean affectLogin)
    {
        if(affectLogin)
            disguises.add(this);

        this.disguise = disguise;
        this.nmsEntity = entity;
    }

    public Disguise(Player disguise, EntityLiving entity)
    {
        this(disguise, entity, true);
    }

    public void send(Player visible)
    {
        if(visible == disguise)
            return;

        EntityPlayer player = NMSUtils.getNMSPlayer(visible);

        nmsEntity.setPosition(player.locX, player.locY, player.locZ);
        nmsEntity.d(disguise.getEntityId());
        nmsEntity.setCustomName(disguise.getDisplayName());
        nmsEntity.setCustomNameVisible(true);

        PacketPlayOutSpawnEntityLiving spawn = new PacketPlayOutSpawnEntityLiving(nmsEntity);
        PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(disguise.getEntityId());

        player.playerConnection.sendPacket(destroy);
        player.playerConnection.sendPacket(spawn);
    }

    public void send(List<Player> visible)
    {
        for(Player player : visible)
            send(player);
    }

    public void send(Player... visible)
    {
        send(Arrays.asList(visible));
    }

    public void send()
    {
        send(new ArrayList<>(Bukkit.getOnlinePlayers()));
    }

    public Player getDisguised()
    {
        return disguise;
    }

    public static HashSet<Disguise> getDisguises()
    {
        return disguises;
    }
}

I also have a static HashSet which stores all the instances made. I am doing this because I want players who login to see the disguise aswell and I want to remove the disguise from the player when the player logs out. Is a static HashSet the way to do it (like I'm doing it)? And if not, how should it be done?

static was asking for it. By its nature, it is prone to "abuse", but that's just part of the challenge.

When all is said and done, if your mod does what you need it to do without bugginess, don't stress too much about best practices at this level of granularity (a particular variable). It's not likely to ever scale in scope to the point where poor design would cause problems for you. It's not a life-support system, after all.

If you want to practice good form for fun, my first instinct would be to move your management logic from Disguise to a (eg) DisguiseManager class, and handle all Disguise creation/destruction through a manager class. Less complex would be private constructor and static create/destroy methods on Disguise. Global side-effects in constructors like you posted is generally bad form.

Basically everytime a constructor is called, you want to add this to a global place.

That's fine, but there are two concerns:

  1. exposing this in constructor is dangerous and requires careful analysis. (your code is buggy in this aspect)
  2. concurrency - if the app is multi-threaded, it needs to be thread-safe. (exposing this in constructor is more problematic in a concurrent environment)
  3. garbage collection - when the object becomes "garbage", how to remove it from the global place.

Using static objects can get really frustrating when your code grows in size, and there are many accessors of the said object. If you were to debug the code, how would you catch the exact code to manipulate the HashSet?

Why don't you refactor the clients using the HashSet, to get it through a getter? What about encapsulation the HashSet instance as a Singleton ? It sounds like only one HashSet is ever created to store Players/Disguies.

Having any sort of getter method, say through Singleton, you could easily add additional code before or after accessing the HashSet. For example, after each usage of the method returning the HashSet, you can print the HashSet's contents. You could do that with static object as well, but the nightmare of finding all the usages of the static object...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM