In the process of making the game, we used a number of design patterns.

MVVM pattern:

We use the MVVM pattern to build our project. This includes view, model and view model. this makes our program more maintainable, testable and extensible.

Single Responsibility Principle:

The following screenshot showcases our EnemyOrc class. This class is only focused on the basic structure and implementation of the EnemyOrc. If we run into any problems with this avatar, we can go to this class to fix any potential issues. This makes it easier for modification and encapsulation.

Creator pattern:

In our code the EnemyFactory() class takes responsibility to create the enemy instances including EnemyOrc, EnemyZombie, EnemyPumpkin, and EnemyAngel. We have these enemy creation classes, including EnemyOrc(), EnemyZombie(), EnemyPumpkin(), and EnemyAngel(), which have the initialization data of the enemies. The EnemyFactory() class aggregates the enemy instances of enemy creation classes.

Polymorphism pattern:

In our code, we use the factory pattern to create the enemy. In the Factory Pattern, polymorphism is achieved through the use of a common interface or base class for all the products (different kinds of enemy in our code) that the factory can create. This common interface allows us to create the enemy interchangeably.

Decorator Pattern:

The decorator pattern is used in the code for the implementation of the power up system. We did this by creating a player decorator abstract class, which has a singular instance variable of a decorated player. We also have the PlayerPowerUp interface, which has the abstract method to apply whatever power up is currently being implemented. The Speed, health, and attack powerup classes implement the applyPowerUp() method, changing the decoratedPlayer as specified by the given class.