我有两个csv文件A和B.A是主存储库。我需要读取这些文件,将B的记录映射到A并将映射的记录保存到另一个文件。 记录的类是保存记录。保存匹配记录的类是RecordMatch。
class Record
{
string Id;
string Name;
string Address;
string City;
string State;
string Zipcode;
}
class RecordMatch
{
string Aid;
string AName;
string Bid;
string BName;
double NameMatchPercent;
}
映射方案如下:首先,针对B的每个记录,使用州,城市和邮政编码过滤A的记录。然后将如此过滤的A的记录与B的记录进行比较。该比较在名称字段之间,并且是使用模糊字符串算法的最佳匹配比较。选择并保存最佳匹配。
字符串匹配算法将给出匹配百分比。因此,必须选择所有比赛中的最佳结果。
现在我尽力解释这个场景,我将谈到设计问题。我最初的设计是制作一个Mapper类,如下所示:
class Mapper
{
List<Record> ReadFromFile(File);
List<Record> FilterData(FilterType);
void Save(List<Record>);
RecordMatch MatchRecord(Record A, Record B);
}
但是看一下设计,它似乎只是一些方法的类包装器。我没有看到任何OO设计。我也觉得Match()更多地属于Record类而不是Mapper类。
但另一方面,我看到这个类实现了类似于Repository模式的东西。
我认为另一种方法是保留Mapper类,并将Match()方法移动到Record类,如下所示:
class Mapper
{
List<Record> ReadFromFile(File);
List<Record> FilterData(FilterType);
void Save(List<Record>);
}
class Record
{
string id;
string name;
string address;
// other fields;
public RecordMatch Match (Record record)
{
// This record will compare the name field with that of the passed Record.
// It will return RecordMatch specifyin the percent of match.
}
}
现在我对这个简单的场景感到困惑。在这种情况下,理想情况下优秀的OO设计是什么?
答案 0 :(得分:4)
有趣的是,我正在研究一个几乎就是这样的项目。
简单回答:好的,首先,如果一个方法在错误的类中暂时不是世界末日!如果您的课程都包含在测试中,那么其中函数的存在非常重要,但可以随着您,域名之王认为合适而流畅地改变。
如果你不测试这个,那么这将是我的第一个建议。许多比我更聪明的人都谈到了TDD和测试如何帮助你的课程自然地达到最佳设计。
更长的答案:我不是在寻找适用于设计的模式,而是喜欢这样思考:每个课程必须改变的原因是什么?如果你将这些原因彼此分开(这是TDD可以帮你做的一件事),那么你将开始看到代码中自然出现的设计模式。
以下是一些改变的原因,我可以通过一些通过阅读你的问题来思考:
好吧,那么,如果实现其中任何一个会使你需要在某处添加“if语句”,那么这可能是实现公共接口的子类的接缝。
另外,假设您要将创建的文件保存在新位置。这是改变的一个原因,不应该与需要改变合并策略的重叠。如果这两个部分属于同一个类,那么该类现在有两个职责,这违反了single responsibility principle。
所以,这是一个非常简短的例子,为了进一步深入了解优秀的OO设计,请查看SOLID principles。学习这些并且在整个OO设计中谨慎应用它们不会出错。
答案 1 :(得分:1)
我试了一下。关于OO原则或我认为的设计模式,你没有那么多,除了可能使用MatchingAlgorithm的组合(如果需要可能还有策略和模板)。这就是我所做的事情:
class Mapper {
map(String fileA, String fileB, String fileC) {
RecordsList a = new RecordsList(fileA);
RecordsList b = new RecordsList(fileB);
MatchingRecordsList c = new MatchingRecordsList();
for(Record rb : b) {
int highestPerc = -1;
MatchingRecords matchingRec;
for(Record ra : a) {
int perc;
rb.setMatchingAlgorithm(someAlgorithmYouVeDefined);
perc = rb.match(ra);
if(perc > highestPerc) {
matchingRec = new MatchingRecords(rb, ra, perc);
}
}
if(matchingRec != null) {
c.add(matchingRec);
}
}
c.saveToFile(fileC);
}
}
class MatchingAlgorithm {
int match(Record b, Record a) {
int result;
// do your magic
return result;
}
}
class Record {
String Id;
String Name;
String Address;
String City;
String State;
String Zipcode;
MatchingAlgorithm alg;
setMatchingAlgorithm(MatchingAlgorithm alg) {
this.alg = alg;
}
int match(Record r) {
int result; -- perc of match
// do the matching by making use of the algorithm
result = alg.match(this, r);
return result;
}
}
class RecordsList implements List<Record> {
RecordsList(file f) {
//create list by reading from csv-file)
}
}
class MatchingRecords {
Record a;
Record b;
int matchingPerc;
MatchingRecords(Record a, Record b, int perc) {
this.a = a;
this.b = b;
this.matchingPerc = perc;
}
}
class MatchingRecordsList {
add(MatchingRecords mr) {
//add
}
saveToFile(file x) {
//save to file
}
}
(这是用Notepad ++编写的,因此可能会出现拼写错误等;而且建议的类肯定会受益于更多的重构,但如果您选择使用此布局,我会留给您。)