I haven't programmed in Java for ages, so I can't quite remember the specifics of the language. But this might help:
The Abilities are quite confusing when you look at their description and try to implement that. Take the
Harvest Ability, for example. The easy way might be to add some code to the 'end of turn' functionality to check if the Pokémon has this Ability and then restore it's berry, etc. When you add ALL Abilities, this becomes unmanagable.
What I was thinking was to make every Ability it's own class (implementing the same interface). A Pokémon has a reference to an instance of it's ability (so we can do PlayerPokemon.ability). For this to work, you should break the abilities down to it's very basics.
Harvest only takes effect at the end of the turn. It then has a 50% chance to restore the held berry of the Pokémon. If the weather is Sunny, it always restore the berry.
This tells us something: the effect only works at the end of the turn. In other words: if we do PlayerPokemon.ability.doAbility() at the end of the turn, it should restore it's berry or not. But we must know it was called because it's the end of the turn. We could pass this as a parameter (kind of like a state) or instead call the method 'doEndOfTurnAbility()' or something like that.
Both options could work: the first one keeps the classes smaller, the second one may make the classes more readable.
Abilities can affect three things, as far as I can remember: the Pokémon with the ability, the opponent or the battle field. Both of those could be an object that's available to the methods in the ability classes. The BattleField object could keep track of things like weather, so our Harvest ability can work. The Pokémon objects keep track of the Pokémon, so things like hold items are also known to the ability object.
And now for attacks. I have no elegant solution, but I do have a solution. There is a design pattern called the 'decorator pattern'. A modified version could work for attacks.
Each effect is again broken down. For example, take an attack that deals both damage and has a chance to cause a status effect to the opponent.
DealDamage and CauseStatus are classes that implement the 'AttackEffect' interface. They both have a field called 'nextEffect' of the type AttackEffect. The constructor for AttackEffects have several parameters, that depent on the class that implement the interface: nextEffect is always present (but nullable), chance, damageToDeal, etc.
Attacks are created like thus:
Attack exampleAttack = new DealDamage(90, 60, 80, new CausesStatus(null, 'poison'));
In order this means: it's a damage dealing attack that has 90 accuracy and deals 60 damage. It also has a 80 chance of inflicting poison to the opponent.
Each AttackEffect class has a 'doEffect' method that works like the 'doAbility' method described above. It has access to both Pokemon objects (to calculate damage, deal damage and inflect the status) and the BattleField object (to things like causing weather). When the doEffect method is called, it also calls 'nextEffect.doEffect'. In our example, this causes the doEffect of the CauseStatus object to be called. Wheter or not the doEffect method of the next effect has to be called is decided by the current attackEffect. This is for chaining Objects.