Код, размещенный на 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();
}
}