jeudi 12 novembre 2020

Alternative to a static interface for Java? (design pattern?)

I've come across a problem while coding with Java where I'd like to be able to use interfaces that include static methods. Since this isn't possible in Java, I'm curious to know what strategies or design patterns I should use instead.

Here's the problem:

  • There are a bunch of entity classes that extend EEntity. Some of these classes implement the Spawnable Interface, which (in the fantasy world where static methods in java interfaces are allowed) returns an object of type SpawnCondition.
  • There is a class called Registrator. Within Registrator, the register function will be called to tell the program about some metadata for each EEntity. For any EEntity that implements Spawnable, I want to add the SpawnCondition to the list called myList.
  • No EEntity / EntityA / EntityB class can be instantiated within Registrator because the EEntity constructor depends on information that is unavailable at the time that Registrator executes (only static member methods may be called within Registrator)

I need to be able to call the static method getSpawnCondition for each Spawnable EEntity. I would like to automate this if at all possible (hence the interface and the janky stuff with classes in the register function).

Other limitations:

  • This code is abstracted from a mod, where some of the source code cannot be edited. Specifically, I cannot change the way EEntity works (and the register function does additional work that is necessary for the code to work, but it can be edited). All other classes and interfaces in the example were defined by me and thus their implementation can be changed completely.

Are there any design patterns that would let me automate the calling of a static method (getSpawnCondition) for classes which implement a specific interface (Spawnable) or that would achieve the same goal in a different way?

(here is a minimum reproducible example)

class EEntity{
    //The constructor of EEntity dictates that EEntities cannot be spawned without a world to spawn them in
    // Therefore, no EEntities can be instantiated before there is a world
}
class EntityA extends EEntity {
    // nothing
}

class EntityB extends EEntity implements Spawnable{
    public static SpawnCondition getSpawnCondition(){
    // sample implementation
        return new SpawnConditon();
    }
}

interface Spawnable(){
    // In a world where static interfaces exist for Java, this is what it would do
    public static SpawnCondition getSpawnCondition();
}

class SpawnCondition(){
    //implementation irrelevant
}

public static class Registrator{
    public static List<SpawnCondition> myList = new ArrayList<SpawnCondition>();

    register("entity_a", EntityA.class);
    register("entity_b", EntityB.class);
    
    
    private <T extends EEntity> void register(String name, Class<T> c){
            // The register function does a bunch of registration stuff that is necessary for each entity (irrelevant to example until the following part:)
            if(Spawnable.class.isAssignableFrom(c)){
                // This seems janky to me and I'm not sure if it would work even if interfaces could have 
                // static methods. However, as long as it's possible to manipulate c into a form where 
                // getSpawnCondition can be called (whether through typecasting or something else) 
                // or if a different parameter can be passed to the register function to achieve the goal I will be happy with the  answer. 

                myList.add(c.getSpawnCondition());
            }
    }
}


Aucun commentaire:

Enregistrer un commentaire