最近,我在网上阅读了一些博客主题,发现在我的职业生涯中,90%的代码行都是程序化的,而不是面向对象的(大耳光)。所以现在,我试着切除我的大脑,以便只产生OOP代码。问题是我对OOP的练习有很多疑问。
这里有一个:
我得到了一个工厂RawLineCollectionFactory,它使用字符串行并从中创建一个名为RawLineCollection的域实体。我的问题是关于参数类型传递到Create方法。
是否应该传递对象(IDataSource),该对象允许我检索这样的字符串行:
public class RawLineCollectionFactory : IRawLineCollectionFactory
{
public IRawLineCollection Create(IDataSource dataSource)
{
ICollection lineGroup = new List();
if (dataSource.GetLines() != null)
{
foreach (string line in dataSource.GetLines())
{
lineGroup.Add(new RawLine(line));
}
}
return new RawLineCollection(lineGroup);
}
}还是在更高的抽象级别上调用dataSource对象的D6,并将结果作为Create方法的参数传递?
public class RawLineCollectionFactory : IRawLineCollectionFactory
{
public IRawLineCollection Create(IEnumerable lines)
{
ICollection lineGroup = new List();
if (lines != null)
{
foreach (string line in lines)
{
lineGroup.Add(new RawLine(line));
}
}
return new RawLineCollection(lineGroup);
}
}编辑:
上下文非常接近应用程序入口点。RawLine是文件中包含游戏创建数据设置的行的对象表示形式。
public class RawLine
{
private string value;
public RawLine(string value)
{
this.value = value;
}
public IEnumerable Split(string separator)
{
if (string.IsNullOrEmpty(separator))
{
throw new ArgumentException("The separator is required");
}
if (!string.IsNullOrEmpty(value))
{
return value
.Replace(" ", "", StringComparison.CurrentCulture)
.Split(separator)
.Where(item => !string.IsNullOrEmpty(item));
}
return Array.Empty();
}
}该类的行为是为特定于应用程序的规则目的拆分他的状态的实际表示,而RawLineCollection是该实体类型的集合。
public class RawLineCollection : IRawLineCollection
{
private readonly IEnumerable lines;
private readonly string separator = "-";
public RawLineCollection(IEnumerable lines)
{
this.lines = lines;
}
public SplittedLineCollection Split()
{
ICollection> result = new List>();
if (IsValidStringGroup(lines))
{
foreach (RawLine line in lines)
{
if (line.Split(separator).Any())
{
result.Add(line.Split(separator));
}
}
}
return new SplittedLineCollection(result);
}
private bool IsValidStringGroup(IEnumerable settingsToSplit)
{
return settingsToSplit != null && settingsToSplit.Any();
}
}RawLineCollectionFactory只使用了一次,比如DataSource.GetLines()方法。
发布于 2020-04-25 22:47:44
谢谢你的问题。IMHO,将过程代码转换为OO代码是一件很好的实践。恭喜你的顿悟!
一般来说,持久化游戏数据的问题是一个序列化问题。我将邀请您探索.NET的本机“设置”功能是否能够满足您的需求。除此之外,标准序列化到JSON或XML可能值得一看。
如果您坚持“滚动您自己的”序列化,您当然可以这样做,以面向对象的方式。我对开始工作的看法如下。
如果您有像游戏级别定义这样的复杂数据,您可能会序列化大量数据,这将更有理由使用标准格式,如JSON或XML。
为了序列化和反序列化一个相对简单的配置文件,您可能可以跳过工厂模式。但是,如果配置跨越多个文件,包括图像块等,那么"Config Factory“可能是值得考虑的。
我建议构建一个(或多个)类来正确地建模实际的配置属性,并将其序列化/反序列化,而不是将所有内容作为字符串处理。
例如:
public class Config
{
public string PlayerName {get; set;}
public DateTime LastPlayed {get; set;}
public int HighScore {get; set;}
} 下面的例子采用“混合”方法。它不仅仅是使用KeyValuePair来处理原始字符串,而是停止了一个完全类型的Config类(如上面所示)。
另一个快速提示:与RawLineCollection不同,我称它为RawLines,甚至更好的是,Lines。
欢迎来到广阔的OOP世界。在我的其他一些代码评审答案中,我深入探讨了指导我的OOP实践的原则。
下面是示例(这段代码编译,但我没有测试它):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class App_ConfigFile
{
/* Config file example
player1Name:Jane
player2Name:Joe
difficulty:medium
lastPlayed:04/20/2020
lastLevel:5
highScore:31000
*/
public void Run()
{
var file = new ConfigFile(@"c:\myGame\config.txt");
var config = file.ToConfigData();
var player1name = config.GetByName("player1Name");
var lastPlayed = DateTime.Parse(config.GetByName("lastPlayed"));
var highScore = int.Parse(config.GetByName("highScore"));
}
}
public class ConfigFile
{
private string path;
private List lines;
public List Lines => lines ?? (lines = getLines());
public bool HasContent => Lines.Count > 0;
public ConfigFile(string path) => this.path = path;
public ConfigData ToConfigData(char separator = ':') => new ConfigData(Lines.Select(l => l.ToKvp(separator)).ToList());
private List getLines() => File.ReadAllLines(path).Select(l => new Line(l)).ToList();
}
public class Line
{
public string Raw { get; private set; }
public Line(string line) => Raw = line;
public KeyValuePair ToKvp(char separator)
{
var tokens = Raw.Split(separator);
return new KeyValuePair(tokens.First(), tokens.Last());
}
}
public class ConfigData
{
private List> data;
private Dictionary _dictionary;
private Dictionary dictionary => _dictionary ?? (_dictionary = data.ToDictionary(d => d.Key, d => d.Value, StringComparer.OrdinalIgnoreCase));
public ConfigData(List> data) => this.data = data;
public string GetByName(string key) => dictionary[key];
public bool TryGetByName(string key, out string value) => dictionary.TryGetValue(key, out value);
}}
https://codereview.stackexchange.com/questions/241148
复制相似问题