How to kill these code blocks in Java?

caller:

switch (type){
            case "creature":
                Creature returnActor2 = getNextCreature();
                boolean isEat2 = actOnNearby(getRightChromosome(Config.HardCode.creature),returnActor2.getLocation());
                if (isEat2) {
                    actOnCreature(returnActor2);
                }
                break;
            case "monster":
                Monster returnActor3 = getNextMonster();
                boolean isEat3 = actOnNearby(getRightChromosome(Config.HardCode.monster),returnActor3.getLocation());
                if (isEat3) {
                    actOnMonster(returnActor3);
                }
                break;
}

It will call the following two methods:

private Monster getNextMonster() {
        ArrayList<Actor> nearbyActors = getActors();
        Monster mine = new Monster();
        for (Actor a : nearbyActors) {
            if (a instanceof Monster) {
                mine = (Monster) a;
            }
        }
        return mine;
    }


private Creature getNextCreature() {
    ArrayList<Actor> nearbyActors = getActors();
    Creature mine = new Creature();
    for (Actor a : nearbyActors) {
        if (a instanceof Creature) {
            mine = (Creature) a;
        }
    }
    return mine;
}

As you can see, the getnextxxxxxx () method is very similar. It only returns different objects with the same logic. How to do? Actonxxxx () also seems to belong to the dry category, but they are roughly the same, using the same logic for different objects How to solve this?

Solution

Let it accept a classtype:

private <T> T getNext(Class<T> type) {
    for (Actor a : getActors()) {
        if (type.isAssignableFrom(a.getClass())) {
            return (T) a;
        }
    }
    return null; //or type.newInstance(); if you want a guaranteed object,but this restricts your constructor.
}

Or use Java 8:

private <T> T getNext(Class<T> type) {
    return (T) getActors().stream()
                .filter(a -> type.isAssignableFrom(a.getClass()))
                .findFirst().orElse(null);
}

But the usage is the same:

Monster next = getNext(Monster.class);

To break this problem, you know two kinds of things:

What do you need?

>Next object of type T. > Method type that determines whether the object is t

What do you have?

>The type you want > a set of objects, one of which may be a new object of type T > through the no args constructor (null if not)

In addition, the only difference between all these methods is one thing: what type it is So we do "turn it into a variable", so it becomes a method parameter

To break this, we just need to organize the code to accomplish this task:

method: //receives a "type" as a parameter
    iterate the list of possible `t`s //our list of objects
        if some_t == type //our comparison,prevIoUsly `a instanceof Type`
            return some_t //our result is found
    return null //or a new object,but essentially our "default"

The only major difference here is:

>Use type Isassignablefrom (some_t.getclass()) replaces some_ T instanceof type

The reason here is that when you use class < T >, this is how you determine this

>Our default value can be null or a new object

Making objects dynamically through reflection limits your options and has the ability to handle exceptions Returning null or empty, optional < T > will help to indicate that you have no result and that the caller can take action accordingly You may just pass the default object itself and return to the instanceof check

Ask yourself the same assumption, "what do I need, what can I provide / have", which will help you break down the problem into smaller steps and solve bigger problems

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>