java—您能用状态模式实现单例模式吗

kcwpcxri  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(276)

我有一个应用程序,我已经工作了一段时间,我了解一点java。
应用程序的范围是以允许重用的方式组合多个设计模式,这些代码无需滚动数百行代码即可编辑。
我实现了一个真正的单例播放器类。我还实现了一个decorator武器类。
我不想为player类添加状态模式,例如alivestate和deadstate。一些简单的东西,让我了解它的工作原理。
为此,我将发布完整的playersingleton类:

public class PlayerSingleton{

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

    private String playerName;
    private Integer playerHealth;

    private Weapon weapon;

    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":
                System.out.println("You have chosen MP5!");
                return new MP5Weapon();

            case "SNIPER":
                System.out.println("You have chosen Sniper!");
                return new SniperRifleWeapon();
            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;
    }

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

    public void attackState(double damage) {
        damage = player.weapon.damage();

    }  
//    @Override
//    public void aliveState() {
//        if(playerHealth >= 1){
//            
//        }
//    }
//    @Override
//    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!");
        }
    }

我曾试图借助头优先设计模式(state)来实现这一点,但是在player类上使用singleton模式意味着我不能从另一个类调用对象。

public class DeadState implements PlayerState{
PlayerSingleton player;

    public DeadState(PlayerSingleton player){
        this.player = player;
    }
    @Override
    public void deadState() {
        System.out.println("You are Dead!");
    }
    @Override
    public void aliveState() {
        System.out.println("You are Dead!");  
    }

}

上面是一个通过playerstate接口实现死态的测试。
有没有任何方法可以通过使用playersingleton的状态模式来实现这一点?
说真的,任何帮助都是了不起的!
另外,如果你能解释一下答案,让我更好地理解。

8ljdwjyq

8ljdwjyq1#

首先你说的这句话:
在player类上使用singleton模式意味着我不能从另一个类调用对象。
实际上,只要您有权访问示例,就可以从其他类调用对象,状态模式就是这样工作的。
为了简单和更好地解释解决方案,我使用了您的类并删除了一些代码,如果您使用此解决方案,您可以添加回我删除的部分代码:
我在代码中使用了两种状态,第一种是playerstate接口,它有两种方法,一种用于承受伤害,另一种用于重生:

public interface PlayerState {
    void respawn();
    void takeDamage(int damage);
}

那么活动状态的实现只有takedamage方法的实现,该方法接收所遭受的伤害量:

public class AliveState implements PlayerState {
    private PlayerSingleton player;

    public AliveState(PlayerSingleton player) {
        this.player = player;
        this.player.setHealth(PlayerSingleton.MAX_PLAYER_HEALTH);
    }

    @Override
    public void takeDamage(int damage) {
        System.out.println(String.format("Suffering %d damage!", damage));
        player.setHealth(player.getHealth() - damage);

        if (player.getHealth() <= 0) {
            player.setLives(player.getLives() - 1);
            player.setState(new DeadState(player));
        }
    }

    @Override
    public void respawn() {
        System.out.println("Nothing to do, player is alive!");
    }

}

对于deadstate的实现也是如此,只要玩家还活着,deadstate只有respawn方法的实现:

public class DeadState implements PlayerState {
    private PlayerSingleton player;

    public DeadState(PlayerSingleton player) {
        this.player = player;
    }

    @Override
    public void takeDamage(int damage) {
        System.out.println("Nothing to do, player is dead!");
    }

    @Override
    public void respawn() {
        if (player.getLives() > 0) {
            System.out.println("respawning to start location!");
            player.setState(new AliveState(player));
        } else {
            System.out.println("Game Over!");
        }
    }

}

最后是playersingleton类,它在创建播放器时被分配state alivestate,takedamage和respawn方法调用当前播放器状态中的实现,如果您注意到,状态实现有一个对播放器示例的引用,因此它们可以更改对象状态。

public class PlayerSingleton {
    public static Integer MAX_PLAYER_HEALTH = 500;
    public static Integer DEFAULT_PLAYER_LIVES = 2;
    private static PlayerSingleton player;

    private Integer health = MAX_PLAYER_HEALTH;
    private int lives = DEFAULT_PLAYER_LIVES;
    private PlayerState playerState;

    private PlayerSingleton() {
        setState(new AliveState(this));
    }

    public static PlayerSingleton getInstance() {
        if (player == null) {
            player = new PlayerSingleton();
        }
        return player;
    }

    public void sufferDamage(int damage) {
        playerState.takeDamage(damage);
    }

    public void respawn(String location) {
        playerState.respawn();
    }

    // Getters and Setters
}

我使用以下主要方法进行测试:

public static void main(String[] args) {
        PlayerSingleton playerSingleton = PlayerSingleton.getInstance();
        playerSingleton.takeDamage(300);
        playerSingleton.respawn();
        playerSingleton.takeDamage(300);
        playerSingleton.respawn();
        playerSingleton.takeDamage(600);
        playerSingleton.respawn();
    }

这就是结果:

Suffering 300 damage!
Nothing to do, player is alive!
Suffering 300 damage!
Player is dead!
respawning to start location!
Suffering 600 damage!
Player is dead!
Game Over!

相关问题