Образец мухи в Java - PullRequest
1 голос
/ 02 мая 2020

Мне попался Шаблон FlyWeight , описанный в ссылке. В приведенном примере я считаю, что будут созданы только 2 реализации объектов проигрывателя. Разве переменная оружия не будет переопределена каждый раз, когда создается объект игрока?

Ответы [ 2 ]

1 голос
/ 02 мая 2020

Код, размещенный на Geeks For Geeks , создает только два изменяемых объекта. Как и следовало ожидать, каждый раз, когда PlayerFactory возвращает игрока, он переопределяет weapon одного из двух объектов. Это можно легко продемонстрировать:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

public class CounterStrike
{

    private static String[] playerType = {"Terrorist", "CounterTerrorist"};
    private static String[] weapons = {"AK-47", "Maverick", "Gut Knife", "Desert Eagle"};

    public static void main(String args[])
    {
        List<Player> players = new ArrayList<>();

        System.out.println("-------  Construction of Players  ----------------");
        for (int i = 0; i < 10; i++)
        {
            Player p = PlayerFactory.getPlayer(getRandPlayerType());
            p.assignWeapon(getRandWeapon());
            p.mission();
            players.add(p);
        }

        System.out.println("-------  Printout all players ----------------");
        for(Player p : players) {
            p.mission();
        }
    }

    public static String getRandPlayerType()
    {
        // Will return 0 or 1
        int randInt =  new Random().nextInt(playerType.length);
        return playerType[randInt];
    }

    public static String getRandWeapon()
    {
        // Will return an integer between 0 inclusive and 5 exclusive
        int randInt = new Random().nextInt(weapons.length);
        return weapons[randInt];
    }
}

interface Player
{
    void assignWeapon(String weapon);
    void mission();
}

class Terrorist implements Player
{
    private final String TASK;
    private String weapon;

    public Terrorist()
    {
        TASK = "PLANT A BOMB";
    }

    @Override
    public void assignWeapon(String weapon)
    {
        this.weapon = weapon;
    }

    @Override
    public void mission()
    {
        System.out.println("Terrorist with weapon " + weapon + "|" + " Task is " + TASK);
    }
}

class CounterTerrorist implements Player
{
    private final String TASK;
    private String weapon;

    public CounterTerrorist()
    {
        TASK = "DIFFUSE BOMB";
    }
    @Override
    public void assignWeapon(String weapon)
    {
        this.weapon = weapon;
    }
    @Override
    public void mission()
    {
        System.out.println("Counter Terrorist with weapon "+ weapon + "|" + " Task is " + TASK);
    }
}

class PlayerFactory
{
    private static HashMap <String, Player> hm =  new HashMap<>();

    public static Player getPlayer(String type)
    {
        Player p = null;

        if (hm.containsKey(type)) {
            p = hm.get(type);
        } else
        {
            switch(type)
            {
            case "Terrorist":
                p = new Terrorist();
                break;
            case "CounterTerrorist":
                p = new CounterTerrorist();
                break;
            default :
                System.out.println("Unreachable code!");
            }

            hm.put(type, p);
        }
        return p;
    }
}

Выходные данные показывают, что у всех террористов есть последнее примененное оружие (Maverick), а у всех CT - AK-47:


Редактировать: Я не исследовал этот шаблон проектирования, но должен сказать, что меня не впечатлил код, опубликованный в Geeks For Geeks. Из того, что я вижу в других примерах атрибуты extrinsi c должны управляться фабрикой. В этом случае я полагаю, что на фабрике должна быть карта для террористов и карта для КТ, где ключом является оружие:
public class CounterStrike
{
    //better use enums
    private static String[] playerType = {"Terrorist", "CounterTerrorist"};
    private static String[] weapons = {"AK-47", "Maverick", "Gut Knife", "Desert Eagle"};

    public static void main(String args[])
    {
        List<Player> players = new ArrayList<>();

        System.out.println("-------  Construction of Players  ----------------");
        for (int i = 0; i < 10; i++)
        {
            String type = getRandPlayerType();
            Player p = type.equals(playerType[0]) ?  PlayerFactory.getTerrorist(getRandWeapon()) :
                PlayerFactory.getCoubterTerrorist(getRandWeapon()) ;
            p.mission();
            players.add(p);
        }

        System.out.println("-------  Printout all players ----------------");
        for(Player p : players) {
            p.mission();
        }
    }

    public static String getRandPlayerType()
    {
        // Will return 0 or 1
        int randInt =  new Random().nextInt(playerType.length);
        return playerType[randInt];
    }

    public static String getRandWeapon()
    {
        // Will return an integer between 0 inclusive and 5 exclusive
        int randInt = new Random().nextInt(weapons.length);
        return weapons[randInt];
    }
}

class PlayerFactory
{
    private static HashMap <String, Player> terrorists =  new HashMap<>();
    private static HashMap <String, Player> cTerrorists =  new HashMap<>();

    public static Player getTerrorist(String weapon)
    {
        Player p = null;

        if (terrorists.containsKey(weapon)) {
            p = terrorists.get(weapon);
        } else{
            p = new Terrorist(weapon);
        }
        terrorists.put(weapon, p);
        return p;
    }

    public static Player getCoubterTerrorist(String weapon)
    {
        Player p = null;

        if (cTerrorists.containsKey(weapon)) {
            p = cTerrorists.get(weapon);
        } else{
            p = new CounterTerrorist(weapon);
        }
        cTerrorists.put(weapon, p);
        return p;
    }
}
interface Player
{
    void mission();
}

class Terrorist implements Player
{
    private final String TASK;
    private String weapon;

    public Terrorist(String weapon)
    {
        this.weapon = weapon;
        TASK = "PLANT A BOMB";
    }

    @Override
    public void mission()
    {
        System.out.println("Terrorist with weapon " + weapon + "|" + " Task is " + TASK);
    }
}

class CounterTerrorist implements Player
{
    private final String TASK;
    private String weapon;

    public CounterTerrorist(String weapon)
    {
        this.weapon = weapon;
        TASK = "DIFFUSE BOMB";
    }

    @Override
    public void mission()
    {
        System.out.println("Counter Terrorist with weapon "+ weapon + "|" + " Task is " + TASK);
    }
}

Мы можем улучшить реализацию, используя перечисления и делая тип игрока внутренним. c атрибут, а не класс:

public class CounterStrike
{
    public enum PlayerType{

        TERRORIST("PLANT A BOMB"), COUNTER_TERRORIST("DIFFUSE BOMB");

        private final String task;

        PlayerType(String task){
            this.task = task;
        }

        String getTask(){ return task;  }
    }

    public enum Weapon {

        AK47("AK-47"), MAVERICK("Maverick"), GUT_KNIFE("Gut Knife"), DESERT_EAGLE("Desert Eagle");

        private final String name;

        Weapon(String name) {   this.name = name;   }

        String getName(){ return name;  }

        @Override
        public String toString() { return name; }
    }

    public static void main(String args[])
    {
        List<Player> players = new ArrayList<>();

        System.out.println("-------  Construction of Players  ----------------");
        for (int i = 0; i < 10; i++)
        {
            Player p = PlayerFactory.getPlayer(getRandPlayerType(), getRandWeapon()) ;
            players.add(p);
            System.out.println("Created: "+ p);
        }

        System.out.println("-------  Printout all players ----------------");
        for(Player p : players) {   System.out.println(p);  }
    }

    public static PlayerType getRandPlayerType()
    {
        int randInt =  new Random().nextInt(PlayerType.values().length);
        return PlayerType.values()[randInt];
    }

    public static Weapon getRandWeapon()
    {
        int randInt =  new Random().nextInt(Weapon.values().length);
        return Weapon.values()[randInt];
    }
}

class PlayerFactory
{
    private static HashMap <Weapon, Player> terrorists =  new HashMap<>();
    private static HashMap <Weapon, Player> cTerrorists =  new HashMap<>();

    static Player getPlayer(PlayerType type, Weapon weapon) {

        return type == PlayerType.TERRORIST ? getTerrorist(weapon) : getCounterTerrorist(weapon);
    }

    private static Player getTerrorist(Weapon weapon)
    {
        Player p = null;

        if (terrorists.containsKey(weapon)) {
            p = terrorists.get(weapon);
        } else{
            p = new Player(PlayerType.TERRORIST, weapon);
        }
        terrorists.put(weapon, p);
        return p;
    }

    private static Player getCounterTerrorist(Weapon weapon)
    {
        Player p = null;

        if (cTerrorists.containsKey(weapon)) {
            p = cTerrorists.get(weapon);
        } else{
            p = new Player(PlayerType.COUNTER_TERRORIST, weapon);
        }
        cTerrorists.put(weapon, p);
        return p;
    }
}

class Player
{
    private final Weapon weapon;
    private final PlayerType type;

    Player(PlayerType type, Weapon weapon) {
        this.type = type;
        this.weapon = weapon;
    }

    Weapon getWeapon() { return weapon; }

    PlayerType getType() {return type; }

    String getTask() {  return type.getTask(); }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(type == PlayerType.TERRORIST ? "Terrorist" : "Counter Terrorist" );
        sb.append(" armed with ").append(weapon).append(". Task: ").append(type.getTask());
        return sb.toString();
    }
}
1 голос
/ 02 мая 2020

В примере диаграммы классов, приведенной автором Geeks for Geeks

Class Diagram

Если я правильно понимаю, игра создает один экземпляр Terrorist, один экземпляр CounterTerrorist и n экземпляры Player, созданные PlayerFactory.

Код отражает диаграмму. Terrorist и CounterTerrorist реализуют интерфейс Player.

Каждый экземпляр Player, созданный PlayerFactory, использует информацию из экземпляра Terrorist или CounterTerrorist, в зависимости от того, с какой стороны плеер включен Поскольку для каждого игрока есть экземпляр Player (обычно 10 в CounterStrike, по 5 на каждой стороне), нет никакой путаницы относительно того, какой игрок какой.

Класс CounterStrike управляет Map, созданным PlayerFactory.

Этот простой пример из реальной жизни минимизирует дублирование, которое могло бы произойти, если бы было только n Player экземпляров. Каждый экземпляр Player должен был бы содержать информацию как для террориста, так и для контртеррориста.

Создав один экземпляр Terrorist, один экземпляр CounterTerrorist и передав эти экземпляры * В 1039 * случаях общий объем памяти для игровых полей уменьшается.

Код игры, вероятно, легче отлаживать и управлять им.

Код Java можно найти на Вундеркинды Для гиков .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...