我有一个界面,有6种方法用于管理数据集。实现之间唯一不同的方法是getSerializedVersion()
和能够解析序列化字符串的构造函数。
public interface DataSets {
public void addEntry(...);
public void removeEntry(...);
public void manipulateEntry(...);
public SomeType getEntry(...);
public List<SomeType> getAllEntries();
// This differs:
public String getSerializedVersion()
}
我无法更改界面。
我的第一个想法是生成一个抽象类并实现前五个方法。对于具体实现(例如DataSetsXML
,DataSetsYAML
,...),我只需要实现getSerializedVersion()
以及能够读取String并初始化对象的构造函数。
为了使其更易于测试,不同的设计可能会更好(https://stackoverflow.com/a/7569581),但哪一个?
答案可能是主观的,但我认为不同方法有一些一般规则或至少(客观)优点和缺点,......
答案 0 :(得分:9)
根据您的解释,差异是与类的行为无关的东西,而是它是如何序列化和反序列化的。我的意思是DataSetsXML
和DataSetsYAML
具有相同的功能,但它们会被序列化为不同的格式。
这意味着保持getSerializedVersion()
与DataSets
类相结合没有任何好处。你应该完全解耦它们。
您可以使用序列化界面:
interface DataSetsSerializer
{
public DataSets unserialize(String string);
public String serialize(DataSets sets);
}
然后在这个类中处理不同的实现,例如:
class YAMLDataSetsSerializer implements DataSetsSerializer
{
public DataSets unserialize(String string) {
DataSets sets = new DataSets();
...
}
public String serialize(DataSets sets) {
...
}
}
通过详细阐述JB Nizet评论,如果你必须在DataSetsSerializer
实例中保留一个DataSets
(恕我直言,因为它们在任何情况下都应该解耦,因为它是一种特定的序列化方式不应该绑定到要序列化的数据)然后方法如下:
class DataSets {
final private DataSetsSerializer serializer;
public DataSets(DataSetsSerializer serializer, String data) {
this.serializer = serializer;
serializer.unserialize(this, data);
}
@Override
public String getSerializedVersion() {
return serializer.serialize(this);
}
}
这需要对建议的界面稍作改动,这不是一个聪明的设计,但它尊重您的要求。
答案 1 :(得分:1)
我认为使用抽象类是合理的。您可以测试抽象类的具体实现(它也间接测试抽象类)。