mercredi 9 décembre 2020

Singleton with State design Patterns

The scope of the application, building a small game using multiple design patterns(Singleton, State, Decorator, Strategy). The Singleton has been done on the Player class, the decorators have been done with accessories on the weapon. The strategy will be eventually done on the player dealDamage playerRecieveDamage.

My question is how would I possible go about using a State Pattern on a player class that is using a Singleton?

import gundecoratorpattern.Guns.Weapon;
import gundecoratorpattern.Accessories.BasicSilencer;
import gundecoratorpattern.Accessories.BasicSight;
import gundecoratorpattern.Accessories.BasicStock;
import gundecoratorpattern.Accessories.GoodSight;
import gundecoratorpattern.Accessories.GoodSilencer;
import gundecoratorpattern.Accessories.GoodStock;
import gundecoratorpattern.Accessories.GreatSight;
import gundecoratorpattern.Accessories.GreatSilencer;
import gundecoratorpattern.Accessories.GreatStock;
import gundecoratorpattern.Guns.MP5Weapon;
import gundecoratorpattern.Guns.ShotgunWeapon;
import gundecoratorpattern.Guns.SniperRifleWeapon;
import java.util.Scanner;

public class PlayerSingleton {

    private static PlayerSingleton player;
    Scanner scanner = new Scanner(System.in);

    private String playerName;
    private Integer playerHealth;

    private Weapon weapon;

//    Weapon stockMP5 = new MP5Weapon();
//    Weapon sniper = new SniperRifleWeapon();
//    Weapon shotgun = new ShotgunWeapon();
    private PlayerSingleton(Weapon weapon, String pName, int pHealth) {
        this.weapon = weapon;
        playerName = pName;
        playerHealth = pHealth;
    }

    public static Weapon chooseWeapon(String choice) {
        switch (choice) {
            case "MP5":
            case "Mp5":
            case "mp5":
            case "mP5":
                System.out.println("You have chosen MP5!");
                return new MP5Weapon();
            case "sniper":
            case "Sniper":
            case "SNIPER":
                System.out.println("You have chosen Sniper!");
                return new SniperRifleWeapon();
            case "Shotgun":
            case "SHOTGUN":
                System.out.println("You have chosen Shotgun!");
                return new ShotgunWeapon();
            default:
                System.out.println("No gun by that name found!");
                return null;
        }
    }

    public static PlayerSingleton getInstance(String choice, String name, int health) {
        System.out.println("Choose Weapon to play the with: ");

        Weapon weapon = PlayerSingleton.chooseWeapon(choice);
        weapon.getDescription();
        if (player == null) {
            player = new PlayerSingleton(weapon, name, health);
        }
        return player;
    }

    PlayerSingleton() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void getWeaponDamage(Weapon damage) {
        
        System.out.println("Damage of weapon: " + weapon.damage());
        
    }

    public void attackState(String choice) {
        Weapon weapon = PlayerSingleton.chooseWeapon(choice);
        System.out.println(player.weapon.damage());
    }
    public void takeHealthPotion() {
        
    }

    public void deadState() {
        if(playerHealth ==0){
          System.out.println("You are dead");
            System.out.println("GameOver");
        }
        
    }

    public void chosenWeapon() {
        System.out.println("Player Info: " + playerName + " " + "Has: " + playerHealth + " health");
        System.out.println(weapon.getDescription() + ":" + " base damage: " + weapon.damage());
    }

    public void addBasicAttachment(String attachment) {
        switch (attachment) {
            case "sight":
                weapon = new BasicSight(weapon);
                break;
            case "silencer":
                weapon = new BasicSilencer(weapon);
                break;
            case "stock":
                weapon = new BasicStock(weapon);
                break;
            default:
                System.out.println("No Attachment found!");
        }
    }

    public void addGoodAttachment(String attachment) {
        switch (attachment) {
            case "sight":
                weapon = new GoodSight(weapon);
                break;
            case "silencer":
                weapon = new GoodSilencer(weapon);
                break;
            case "stock":
                weapon = new GoodStock(weapon);
                break;
            default:
                System.out.println("No Attachment found!");
        }
    }

    public void addGreattAttachment(String attachment) {
        switch (attachment) {
            case "sight":
                weapon = new GreatSight(weapon);
                break;
            case "silencer":
                weapon = new GreatSilencer(weapon);
                break;
            case "stock":
                weapon = new GreatStock(weapon);
                break;
            default:
                System.out.println("No Attachment found!");
        }
    }
}

Ill post the main just here, so there is more understanding on how the weapon object is being called.

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Choose Weapon to play the with: ");
        System.out.println("'Shotgun' for Shotgun");
        System.out.println("'Sniper' for Sniper");
        System.out.println("'MP5' for MP5");
        String chooseWeapon = scanner.next();
        System.out.println("Please Enter your name before Beginning*");
        String name = scanner.nextLine();
        PlayerSingleton player = PlayerSingleton.getInstance(chooseWeapon, name, 100);
        System.out.println();
        player.chosenWeapon();   //Prints out details of the chosen weapon, weight damage etc.
        System.out.println();
    }
public abstract class Weapon {
    String description = "Unknown Weapon: ";
    
    
    public String getDescription(){
        return description;
    }
    //public abstract int bulletCount();
    public abstract double weight();
    public abstract double damage();
}

The above is an abstract weapon class which the guns are made from.

public class MP5Weapon extends Weapon {

    public MP5Weapon() {
        description = "Base Weapon is MP5";
    }

    public int bulletCount() {
        return 27;
    }

    @Override
    public double weight() {
        return 12;
    }

    @Override
    public double damage() {
        return 13;
    }

This is the MP5 weapon created from the abstract Weapon class.

Now all this code works perfectly fine, in the main the user can choose what weapon they want by typing in MP5. Which results in a true Singleton Player class.

But how do I go about making a Singleton Player Class using a state pattern.

I have tried using the following method:

Below is the PlayerState interface:


public interface PlayerState {
    void action(PlayerSingleton player);
}

Again for convenience sake ill just show State Context class and one State method.

public class StateContext{
  
    private PlayerState state = null;

    public void setState(PlayerState state) {
        this.state = state;
    }
    public void gameAction() {
        state.action();            //I have an issue with this line no arg after .action
                                   //required PlayerSingleton, found no argument
    }
}
public class HealthyState implements PlayerState{
    
    @Override
    public void action(PlayerSingleton player) {
        player.attackState();    //This line also produced an error. It is meant to return the weapon damage of chosen weapon. //requires double from Weapon weapon but not sure how to bring it in here. Maybe weapon weapon.damage? 
    }   
}

As mentioned above, the player must have a singleton pattern, in the PlayerSingleton class, the user has a choice of weapons to choose from, once selected the player class is initialised and the user is forced to play with that weapon throughout the game.

My question is or want to understand is based on all the classes above, how to implement a state pattern of attackState, healState and deadState with a singleton player class.

Any help is appreciated!

Aucun commentaire:

Enregistrer un commentaire