Inheritance vs Injection with Template-ish pattern and planned contributors

I’m trying to develop an OSGi application to handle my game engine. This game engine will be making use of the Entity-Component-System pattern. Part of this pattern is the use of GameSystems.

I had initially planned on exposing the GameSystem interface as its own bundle; this way other contributors can create their own systems and add them to the game engine via OSGi bundles. When I wrote up the initial interface it looked like

public interface GameSystem {      boolean isInterestedIn(GameEntity entity);      void update(GameEntity entity); } 

Then I wrote an abstract implementation of this to add some precondition checking (returning false if the entity is null).

public abstract class AbstractGameSystem implements GameSystem {      public boolean isInterestedIn(GameEntity entity) {         if (entity == null) {             return false;         }         // TODO     } } 

At this point I realized I needed some sort of mechanism for allowing the subclass to add their own conditions, without being forced to call super.isInterestedIn(entity). I created a protected abstract method that subclasses could implement.

public abstract class AbstractGameSystem implements GameSystem {      protected abstract boolean checkEntity(GameEntity entity);      public final boolean isInterestedIn(GameEntity entity) {         if (entity == null) {             return false;         }         return checkEntity(entity);     } } 

At this point I take a step back and wonder if maybe I should, instead of depending on inheritance, pass a predicate and consumer as constructor parameters, and not bother with an abstract class at all.

public final class InjectedGameSystem implements GameSystem {      private final Predicate<GameEntity> predicate;     private final Consumer<GameEntity> consumer;      public InjectedGameSystem(Predicate<GameEntity> predicate, Consumer<GameEntity> consumer) {         this.predicate = Objects.requireNonNull(predicate);         this.consumer = Objects.requireNonNull(consumer);     }      public boolean isInterestedIn(GameEntity entity) {         return predicate.test(entity);     }      public void update(GameEntity entity) {         consumer.accept(entity);     } } 

The expected execution of this code would be in the game engine, something like

public void run() {     while (shouldRun()) {         for (GameEntity entity : entities) {             for (GameSystem system : systems) {                 if (system.isInterestedIn(entity)) {                     system.update(entity);                 }             }         }     } } 

This revealed an interesting question in my head. If I always expect a piece of code to be run in a certain way (call isInterestedIn followed by update if it returns true), and if I provide a way of delegating all functionality to other objects (the predicate and consumer), is there any reason to provide the interface at all, instead of just the delegating class?