英文:
Flyweight Pattern in Java
问题
我在链接中看到了享元模式(FlyWeight Pattern)的描述。在提供的示例中,我相信只会创建2个玩家对象的实现。难道不会在每次创建玩家对象时覆盖武器变量吗?
英文:
I came across FlyWeight Pattern described in the link. In the example provided , I believe only 2 implementations of player objects will be created. Wouldn't the weapons variable be overridden each time a player object is created?
答案1
得分: 1
在Geeks for Geeks的作者提供的示例类图中:
(图片链接)
如果我理解正确,游戏创建了一个Terrorist
实例,一个CounterTerrorist
实例,以及由PlayerFactory
创建的n
个Player
实例。
代码反映了这个类图。Terrorist
和CounterTerrorist
都实现了Player
接口。
由PlayerFactory
创建的每个Player
实例都使用来自Terrorist
或CounterTerrorist
实例的信息,这取决于玩家所在的阵营。由于每个玩家(通常在CounterStrike中为10名,每边5名),都有一个Player
实例,因此不会混淆哪个玩家是哪个。
CounterStrike
类管理由PlayerFactory
创建的Map
。
这个简单的现实世界示例减少了如果只有n
个Player
实例时会发生的重复。每个Player
实例都必须同时保存恐怖分子和反恐分子的信息。
通过创建一个Terrorist
实例,一个CounterTerrorist
实例,并与Player
实例共享这些实例,减少了游戏字段的总存储量。
游戏代码可能也更容易进行调试和管理。
Java代码可以在Geeks For Geeks上找到。
英文:
In the example class diagram given by the Geeks for Geeks author
If I understand this correctly, the game creates one instance of Terrorist
, one instance of CounterTerrorist
, and n
instances of Player
created by the PlayerFactory
.
The code reflects the diagram. Terrorist
and CounterTerrorist
implement the Player
interface.
Each Player
instance created by the PlayerFactory
uses the information from the Terrorist
or CounterTerrorist
instance, depending on which side the player is on. Since there's a Player
instance for each player (Usually 10 in CounterStrike, 5 on each side), there's no confusion as to which player is which.
The CounterStrike
class manages the Map
created by the PlayerFactory
.
This simple real-world example minimizes the duplication that would occur if there were just n
Player
instances. Each Player
instance would have to hold the information for both a terrorist and a counter-terrorist.
By creating one instance of Terrorist
, one instance of CounterTerrorist
, and sharing those instances with the Player
instances, the total amount of storage for the game fields is reduced.
The game code is probably easier to debug and manage as well.
The Java code can be found on Geeks For Geeks.
答案2
得分: 1
以下是您提供的代码部分的翻译:
// ...(略去开头的说明)
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("------- 玩家构造 ----------------");
for (int i = 0; i < 10; i++)
{
Player p = PlayerFactory.getPlayer(getRandPlayerType(), getRandWeapon()) ;
players.add(p);
System.out.println("创建了:" + p);
}
System.out.println("------- 打印所有玩家 ----------------");
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(" 携带武器:").append(weapon).append(". 任务:").append(type.getTask());
return sb.toString();
}
}
请注意,上述翻译中的注释已被省略,只保留了代码部分的翻译。如果您有任何问题或需要进一步帮助,请随时提问。
英文:
The code as posted on Geeks For Geeks constructs only two mutable objects. <br/>
As can be expected, each time PlayerFactory
returns a player, it overrides the weapon
of one of the two objects. <br/>
This can be demonstrated easily:
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;
}
}
The output shows that all Terrorist have the last applied weapon (Maverick) and all CT an AK-47:
<hr>
Edit: I did not explore this design pattern, but I must say I am not impressed by the code posted in Geeks For Geeks.<br/>
From what I see in other examples the extrinsic attributes need to be managed by the factory. <br/>
In this case I guess the factory should have a map for terrorist and a map for CT where the key is the weapon:
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);
}
}
We can improve the implementation by using enums, and making the player type an intrinsic attribute, rather than a class:
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();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论