I believe that the best way is to do something like Essentials.
For moves you can extends the function code main class (PokeBattle_Move, that isn't abstract or interface) and use function codes, a good use of OOP polymorphism. This can be done using a factory method that dinamically instanciate the classes as reading the move data, this can be done with reflection API.
The items are done by procedures (that can be done in java extending an interface using anonymous class). Note that some similar itens uses the same procedule (ItemHandlers::UseOnPokemon.copy(:PARLYZHEAL,:CHERIBERRY)).
The abilities are done using condition in battle cycle, as well the hold items.
A thing that essentials lacks is some more flags in the moves. I believe that we can add an extra flag to moves that can be used to turn the function moves that takes a status effect (poison, burn, among others and even confusion) to only one function move with the status flag. Maybe you can also use this flag as an array.
Maybe is a good thing to do function codes to itens/abilities, like the item stats change (plates), but I disagree that you need to extends every class/implements every interface for every specify effect. I agree with Maruno that is more simple to only read a class attribute (like a code or the name) to do this.
A side note: I have experience with Ruby/Java/Essentials.