I have an ItemData
class in my program that stores saved data about a game inventory item that can change, such as its durability, quality, number of bullets in the clip and similar. ItemClass
, on the other hand, lives in a DLL, and holds data that is always true for specific item, such as its name, max durability, size of the clip and similar, regardless of its state.
I believe the two classes should be combined using some standard design pattern, but I'm not sure how.
ItemClass
is in a DLL that loads data from a specific file type and then presents that data in this form.
public class ItemClass
{
public byte itemVersion;
public int type;
public int timesUsed;
public int quality;
public int meta;
public ItemClass[] parts = new ItemClass[0];
public List<ItemClass> moreParts= new List<ItemClass>();
public bool activated;
public byte index;
//Some methods specific to this class
}
I actually wrote the library, so I could change it, but I would rather not break encapsulation or make the library dependent on the program.
This class is in my program:
public class ItemData
{
public static List<ItemData> itemList = new List<ItemData>();
public const int MAX_QUALITY = 5;
public const int DEFAULT_STACKNUMBER = 100;
public int id;
public string name;
public int stackNumber = 0;
public bool isBlock = false;
public bool hasQuality = false;
public int degradationMin = 0;
public int degradationMax = 0;
public int magazineSize = 0;
public string partType = "";
public string[] morePartsNames;
public string[] partNames;
public string[] magazineItems;
public byte[] iconPixels;
public bool isDeveloper = false;
public static ItemData GetItemDataById(int id)
{
foreach (ItemData itemData in itemList)
{
if (itemData.id == id)
{
return itemData;
}
}
return null;
}
//Some more methods specific to this class
}
The program reads some XML files to extract rules regarding ItemClass
above. There are about 1500 different items with different values and rules. All are stored in a static list in the ItemData
class.
When dealing with the ItemClass
, I need info from ItemData
in order to know how to present the data to the user and how to manipulate it in a way that won't break any of the rules of the item (eg. not allow the user to set bullets in the clip to 10 if clip size is only 8). They are the two sides of the same item.
I can match each ItemClass.type
to exactly one ItemData.id
.
However, I'd like to treat connected ItemClass
and ItemData
as a single class, since they do add up to a single item:
public class ItemBinder
{
public ItemClass itemClass;
public ItemData itemData;
public int type;
public int quality;
public int timesUsed;
public int meta;
public byte ammoIndex;
public bool activated;
public ItemClass[] parts;
public List<ItemClass> moreParts;
public int id;
public string name;
public bool isBlock;
public bool hasQuality;
public int degradationMin;
public int degradationMax;
public int magazineSize;
public string partType;
public string[] morePartsNames;
public string[] partNames;
public string[] magazineItems;
public byte[] iconPixels;
public bool isDeveloper;
public ItemBinder(ItemClass itemClass)
{
this.itemClass = itemClass;
type = itemClass.type;
quality = itemClass.quality;
itemsUsed= itemClass.timesUsed;
meta = itemClass.meta;
ammoIndex = itemClass.ammoIndex;
activated = itemClass.activated;
parts = itemClass.parts;
moreParts = itemClass.moreParts;
itemData = ItemData.GetItemDataById(type);
id = itemData.id;
name = itemData.name;
isBlock = itemData.isBlock;
hasQuality = itemData.hasQuality;
degradationMin = itemData.degradationMin;
degradationMax = itemData.degradationMax;
magazineSize = itemData.magazineSize;
partType = itemData.partType;
morePartsNames = itemData.morePartsNames ;
partNames = itemData.partNames;
magazineItems = itemData.magazineItems;
iconPixels = itemData.iconPixels;
isDeveloper = itemData.isDeveloper;
}
//Some methods for manipulating the class
}
I have this whole situation in two places in my program, and as it expands, there may be more.
I'm guessing that abstract factory would be a way to go here, right? I would give the concrete ItemBinderFactory factory ItemClass as a parameter and it would return appropriate ItemBinder.
But there's an itch that abstract factory isn't scratching, which makes me think this can be improved on another level. Abstract factory would streamline the way this objects are created, but the emphasis here is that the two objects are just two parts of a whole — all fields in both objects are present in the final one. There must be some better way to deal with this.
Also note that the ItemBinder class has to contain additional methods that uses data from both ItemClass and ItemData. So ItemBinder would inherit all the (non-static or const) fields, but none of the methods, and would add some of its own.
ItemData
represents an instance of someItemClass
, and cannot exist independently of anItemClass
, right? Why doesn'tItemData
have any reference to itsItemClass
? \$\endgroup\$