我在玩火车游戏。我需要序列化每个级别使用哪一列火车。所以我可以简单地做:
public class Level {
Track track;
Train train;
[...]
}
public class Train {
Wagon[] wagons;
}
public class Wagon {
float length;
float weight;
}
//Example:
level = new Level (track, new Wagon (1f,2f));但是,我需要有一种类型的马车,我可以选择。就像这样:
public class Wagon {
float length;
float weight;
public static Wagon Small { get { return new Wagon (1f,2f); }}
public static Wagon Big { get { return new Wagon (10f,20f); }}
}
//Example:
level = new Level (track, Wagon.Small);这是可行的。但是,如果我想调整一个货车参数,我必须反序列化,修改和重新序列化每辆货车。
所以我想出了这个:
public enum WagonType {
Small,
Big
}
public class WagonParams {
float length;
float weight;
}
public class Wagon {
WagonType type;
WagonParams params { get { return WagonFactory.GetParams(type); }}
}
public WagonFactory {
static WagonParams small;
static WagonParams big;
static WagonFactory () {
small = new WagonParams (1f,2f);
big = new WagonParams (10f,20f);
}
public static WagonParams GetParams (WagonType type) {
switch (type) {
case WagonType.Small: return small;
case WagonType.Big: return big;
}
}
}
//Example:
level = new Level (track, new Wagon(WagonType.Small));这看上去有点过火,但有效。
现在假设我想要一个SmallWagon,但是如果有更多的重量,我可以这样做:
public interface IOverrideWagonField {
WagonParams Override (WagonParams params);
}
public class OverrideWeight : IOverrideWagonField {
float weight;
WagonParams Override (WagonParams params) {
return new WagonParams (params.length, weight);
}
}
public class Wagon {
WagonType type;
IOverrideField overrider;
WagonParams params { get { return WagonFactory.GetParams(type,overrider); }}
}
public WagonFactory {
static WagonParams small;
static WagonParams big;
static WagonFactory () {
small = new WagonParams (1f,2f);
big = new WagonParams (10f,20f);
}
public static WagonParams GetParams (WagonType type, IOverrideWagonField overrider) {
switch (type) {
case WagonType.Small: return overrider != null? overrider.Override(small) : small;
case WagonType.Big: return overrider != null? overrider.Override(big) : big;
}
}
}
//Example:
level = new Level(track, new Wagon(WagonType.Small,null)); //Normal Wagon
level = new Level(track, new Wagon(WagonType.Small,new OverrideWeight (23f)); //Override weight困扰我(除了复杂性)的是,每辆马车都使用内存作为他们可能不使用的IOverrideWagonField。
如果要覆盖多个字段,则系统会出现缺陷。它需要一个IOverrideWagonField数组,但它将为每个overrode字段创建一个新的对象。(重写()方法调用"new")
所以我觉得这个制度还很不完善。
你认为如何?你将如何实施这样一个系统?
发布于 2016-08-13 23:24:46
看起来像一个过度工程的案例,我个人会保持它简单:对待所有的货车一样。
public class Wagon
{
public float Length { get; set; }
public float Weight { get; set; }
}
public class Train
{
public List<Wagon> Wagons { get; set; }
}
public class Level
{
public Train Train { get; set; }
public static Level Deserialize(TextReader textReader)
{
if (textReader == null) throw new ArgumentNullException(nameof(textReader));
var serializer = new XmlSerializer(typeof(Level));
var deserialize = serializer.Deserialize(textReader);
var level = deserialize as Level;
return level;
}
public static void Serialize(TextWriter textWriter, Level level)
{
if (textWriter == null) throw new ArgumentNullException(nameof(textWriter));
if (level == null) throw new ArgumentNullException(nameof(level));
var serializer = new XmlSerializer(typeof(Level));
serializer.Serialize(textWriter, level);
}
}public class Demo
{
public Demo()
{
// some level
var level = new Level
{
Train = new Train
{
Wagons = new List<Wagon>(new[]
{
new Wagon
{
Length = 100.0f,
Weight = 100.0f
},
new Wagon
{
Length = 200.0f,
Weight = 200.0f
}
})
}
};
// serialize
string xml;
using (var writer = new StringWriter())
{
Level.Serialize(writer, level);
xml = writer.ToString();
}
// deserialize
using (var reader = new StringReader(xml))
{
var level1 = Level.Deserialize(reader);
}
}
}Wagon子类如下所示:public class SmallWagon : Wagon
{
public SmallWagon()
{
Length = 10.0f;
Weight = 10.0f;
}
}
public class LargeWagon : Wagon
{
public LargeWagon()
{
Length = 10000.0f;
Weight = 10000.0f;
}
}但是您必须将这些类型包含在Wagon中,才能使序列化工作:
[XmlInclude(typeof(SmallWagon))]
[XmlInclude(typeof(LargeWagon))]
public class Wagon
{
public float Length { get; set; }
public float Weight { get; set; }
}您可以通过自动收集它们并使用其他构造函数来减轻这种繁琐的工作:
var extraTypes = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(s => s.BaseType == typeof(Wagon))
.ToArray();
var serializer = new XmlSerializer(typeof(Level), extraTypes);尽管如此,感觉还是像一种代码气味,因为现在有许多类型的货车:
<?xml version="1.0" encoding="utf-16"?>
<Level xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Train>
<Wagons>
<Wagon xsi:type="SmallWagon">
<Length>10</Length>
<Weight>10</Weight>
</Wagon>
<Wagon xsi:type="LargeWagon">
<Length>10000</Length>
<Weight>10000</Weight>
</Wagon>
<Wagon>
<Length>100</Length>
<Weight>100</Weight>
</Wagon>
<Wagon>
<Length>200</Length>
<Weight>200</Weight>
</Wagon>
</Wagons>
</Train>
</Level>为了简化构建预置货车的过程,我要么使用一些静态类,要么使用一些原始构建器系统:
public static class WagonHelper
{
public static Wagon CreateLargeWagon()
{
return new Wagon
{
Length = 10000.0f,
Weight = 10000.0f
};
}
public static Wagon CreateSmallWagon()
{
return new Wagon
{
Length = 10.0f,
Weight = 10.0f
};
}
}
// or
public abstract class WagonBuilder
{
public abstract Wagon Build();
}
public class LargeWagonBuilder : WagonBuilder
{
public override Wagon Build()
{
return new Wagon
{
Length = 10000.0f,
Weight = 10000.0f
};
}
}坚持接吻原则,
现在,关于多次序列化,它没有什么问题,Unity3D经常这样做,以处理诸如在重新构建后重新加载程序集之类的事情。
https://softwareengineering.stackexchange.com/questions/328315
复制相似问题