Using an interface in oops for the strategy pattern
I was going to comment on this blog https://blogs.sap.com/2018/04/05/opensap-abap-unit-testing-course-getting-lost-in-the-weeds/ but decided instead to write my own in response!
There’s a Russian card game call Durak. A great game, in many ways quite different from those played in Western Europe. The play it in Vietnam as well from the time Soviet military advisors were assisting the country. My wife taught it to me, but we didn’t know the name, so in the family we call it “beating up on stupid”. Not too far from the actual name, which means “fool”. One time I was helping out at a Russian orphanage. The kids were surprised to find this Englishman who knew their favourite card game. It’s quite a vicious game – worth learning!
My son was doing a project for his Matura, and decided to study the game from a mathematical perspective, involving rudimentary game theory. I thought it might be helpful for him if I wrote an emulator. After a few days effort I had one up and running in Java. One of the few times I’ve managed to impress him. He works as a programmer now, so it probably won’t happen again. Very smart man, my son.
Anyway, the idea was to have a number of computer controlled players playing each other, and see who would win. What we wanted though, was to play thousands of games, to really test various strategies. For simplicity, since the game isn’t entirely turn based, we limited the simulation to 2 players. That way we have one defender and one attacker, rather than multiple attackers.
Within my game engine, I have an instance of a player class representing each player. Each player can have a different strategy for playing. For example, one may always play the highest card. Another may play at random. Or there may be something far more complex. So I created an attribute for player to hold an instance of a strategy class.
The thing about the different strategies is, however, that they don’t really have much in common except that they suggest which card to play. I could have created a super class with an abstract method like choose_card_to_play and had all my various strategies as subclasses of that superclass, implementing different versions of choose_card_to_play. But a class with only abstract methods (remember, the direct subclasses are unlikely to have anything in common) is an interface.
So I created an interface, called, funnily enough, strategy, with a method called choose_card_to_play, with importing parameter of (for example) game_state and exporting the card to play. Each of my player instances has an attribute which is, in ABAP parlance, type ref to strategy. All the different strategy classes I might have will implement the interface strategy and slot right in.
Somewhere, I’ll have to specify the concrete class that implements strategy for a player, but after that I can forget about the details. I might even have something that allows the chosen strategy to change during the game. The point is, that if I come up with a new strategy, I create a class for it, and change the place in the game engine where strategies are chosen (and there are ways of even obviating that requirement), without having to change any other method that uses a strategy.
Sure, I don’t have to do it that way. I could use multiple if…elseif…elseif… or case statements or the like. But using an interface reduces complexity and increases flexibility while requiring minimal changes. That’s one of the most useful concepts, I think, in object oriented programming – that you can abstract complexity easily out of your program.