Проблемы с развязкой в ​​Java с помощью операторов switch

в настоящее время я делаю небольшую игру, в которой в моем классе игроков очень много важных вещей и зависимостей.

Поэтому я решил выделить операторы switch в отдельный класс, который будет вызываться в методе.

Для контекста код игрока

import Accessories.BasicSight;
import Accessories.BasicSilencer;
import Accessories.BasicStock;
import Accessories.GoodSight;
import Accessories.GoodSilencer;
import Accessories.GoodStock;
import Accessories.GreatSight;
import Accessories.GreatSilencer;
import Accessories.GreatStock;
import PlayerState.AliveState;
import PlayerState.PlayerState;
import Guns.Weapon;
import Guns.*;

import java.util.Scanner;

public class PlayerSingleton {

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

    private String playerName;
    private int lives;
    private Integer health;
    public static Integer MAX_PLAYER_HEALTH = 500;
    public static Integer DEFAULT_PLAYER_LIVES = 2;

    private PlayerState playerState;

    private Weapon weapon;

    private PlayerSingleton(Weapon weapon, String pName) {
        this.weapon = weapon;
        this.playerName = pName;
        this.lives = DEFAULT_PLAYER_LIVES;
        setState(new AliveState(this));
    }

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

        Weapon weapon = PlayerSingleton.chooseWeapon(choice);

        weapon.getDescription();

        if (player == null) {
            player = new PlayerSingleton(weapon, name);
        }
        return player;
    }

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

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

    public int getLives() {
        return lives;
    }

    public void setLives(int lives) {
        this.lives = DEFAULT_PLAYER_LIVES;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(Integer health) {
        this.health = health;
    }

    public void setState(PlayerState playerState) {
        this.playerState = playerState;
    }

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

    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 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 getBasicAttachment(String attachment) {

    }

    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 addGreatAttachment(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!");
        }
    }
    
}

Таким образом, приведенный выше код — это мой класс Player, я хотел бы поместить вложения оружия addBasic/Good/Great в другой отдельный файл класса, чтобы затем обеспечить лучшую развязку кода. Я не уверен, как это сделать с помощью оператора switch.

Любые идеи о том, как подойти к этому?

Редактировать:

Методы переключения вызываются из основного:

import Accessories.*;
import Player.PlayerSingleton;
import Guns.Weapon;
import Guns.MP5Weapon;
import java.util.Scanner;

public class FireingRange {
Weapon weapon;
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        
        String name = scanner.nextLine();
      
        System.out.println(name + " to begin the game, first type a weapon you would like to play with:");
        System.out.println();
        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().toUpperCase();

        PlayerSingleton player = PlayerSingleton.getInstance(chooseWeapon, name);
       
        System.out.println(player.getHealth());
        System.out.println(player.getLives());

       
        System.out.println();
      
        player.chosenWeapon();
        System.out.println("Are you ready to play the game?");

    }

Класс абстрактных аксессуаров:

import Guns.Weapon;

public abstract class AccessoryDecorator extends Weapon{
    public abstract String getDescription();
}

Аксессуар, расширяющий AccessoryDecorator:

public class BasicSight extends AccessoryDecorator {
    Weapon weapon;
    
    public BasicSight(Weapon weapon) {
        this.weapon = weapon;
    }
    @Override
    public String getDescription() {
        return weapon.getDescription() + ", Basic Sight";
    } 
    @Override
    public double weight() {
        return 7 + weapon.weight();
    }

    
    @Override
    public double damage() {
        return 7 + 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 addGreatAttachment(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!");
        }
    }

В своем собственном классе, чтобы затем иметь возможность вызывать переключатель с результатом, который затем добавляется к значениям выбранного оружия.

Кажется, я не могу сообразить, как вернуть аксессуар в зависимости от того, какой аксессуар создан.

Почему они здесь в первую очередь? Откуда их вызывают?

Thiyagu 13.12.2020 04:15
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете создать базовый класс с некоторой функциональностью, а затем добавить код с помощью расширения. Другой вариант — создать служебный класс только со статическими функциями, которые вы можете вызывать для управления переданным объектом, например:

public class PlayerUtil {
    public static void addGreatAttachment(PlayerSingleton player, String attachment) {
        Weapon weapon;
        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!");
        }
        player.setWeapon(weapon);
    }
}

Но в вашем случае я рекомендую вам создать еще один класс: «EquipedWeapon». Этот класс будет иметь собственное поле «Оружие» и, возможно, несколько полей «Вложение». Вы можете поместить туда код для смены насадок и даже добавить некоторые методы для получения статистики об оружии с надетыми на него насадками, например урон, разброс пуль или wtv, а затем создать геттер для оружия внутри PlayerSingleton.

Я бы также рекомендовал создать в вашей игре класс AttachmentManager, который содержит все вложения и позволяет вам выбирать их с помощью различных методов. Или вы можете сделать так, чтобы все вложения расширяли один класс Attachment, содержащий статический список всех вложений. Если вы добавите имя в качестве поля внутри класса вложения, вы сможете создать статический метод, который выполняет итерацию по всем вложениям, находит одно с правильным именем и возвращает его. Или используйте статический Hashmap<String, Attachment>.

Вы часто можете исключить операторы switch в языках с наследованием классов, таких как Java. Особенно гибкие перечисления Java. У меня есть пример, который делает это:

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

public enum CommandEnum
{
    AUTHENTICATE("authenticate") {
        public Command newCommand(final String newMessageName) {
            return new Authenticate(newMessageName);
        }
    },

    ADD("add") {
        public Command newCommand(final String newMessageName) {
            return new Add(newMessageName);
        }
    },
    // ...bunch deleted for brevity    

    public final String messageName;

    // Collect all enumerations into a map you
    // can look up by name.    
    private static final Map<String, CommandEnum> messageNameMap =
        Arrays.stream(CommandEnum.values())
            .collect(
                Collectors.toMap(
                    commandEnum -> commandEnum.messageName,
                    commandEnum -> commandEnum
                )
            );


    CommandEnum(final String newMessageName) {
        messageName = newMessageName;
    }


    public abstract Command newCommand(final String newMessageName);

    public Command newCommand() {
        return newCommand(messageName);
    }


    public static CommandEnum getEnum(String messageName) {
        return messageNameMap.get(messageName);
    }
}

В этом случае вы получите перечисление из строки следующим образом:

CommandEnum ce = CommandEnum.getEnum(...string...);

И вы преобразуете его в команду следующим образом:

if (null != ce) {
    Command c = ce.newCommand();
    ...
}

Другие вопросы по теме