我有一个实现某些功能的抽象类,比方说FileFormat
。对于我想支持的每种文件格式,我都有一个子类,例如ZipFileFormat
或TextFileFormat
。文件格式的某些功能是有状态的,例如将文件转换为文本流的操作。但是其他一些功能没有状态,例如默认文件扩展名或文件内容的魔术模式前缀。
表示这种情况的一种方法是使用一个可以覆盖的抽象方法来提供属性:
abstract String getDefaultExtension();
...
String getDefaultExtension() { return "txt"; }
这样可行,但无法表达基类对此属性的假设。在这种情况下,FileFormat
API的客户端会假设getDefaultExtension()
的返回值永远不会随时间而变化。但是使用覆盖,无法在子类中声明此意图或在基类中声明限制。
另一种方法是使用成员变量。在这种情况下,格式的默认扩展名的值将传递给基类构造函数。但这并不是很好,因为它会在我们类的每个实例中占用存储空间 - 在文件扩展名的情况下,所有实例都将具有相同的扩展名。
另一种方法是Properties
对象类型解决方案,其中你有一个结构包含一袋设置,这些设置可以是静态的,也可以是静态的,但是会失去类型安全性,API文档等等。
还有其他选项或评论吗?感谢。
答案 0 :(得分:0)
至少使用Java,如果将它存储为类的字段,它实际上不会占用额外的空间。
说你有
String fileExtension="txt";
Java不会让类的每个实例存储txt
String
,而只是让它们引用回原始副本。
您也可以
static final String fileExtension = "txt";
这将使该字段在所有类的实例中具有通用性,并且无法更改(在Java字符串中是不可变的。当我提到'更改'字符串时,我并不是指更改字符串中的单个字符。而是fileExtension="bfr";
会使fileExtension
指向一个新的String
对象,并为其分配bfr
值。
答案 1 :(得分:0)
短串的扩散真的很重要吗?
除此之外,没有什么好方法可以在课堂之外指定不可变性,而不是作为评论。
您可以使用static final
常量并在getter中返回该常量以避免重复数据。在Javadocs中使用@see
来生成常量,并使用getter相互引用。
不知道这是否比带有文字的getter更好,而不是轻微的语义。
我想,你可以让每个子类注册自己的扩展名。
您始终可以使用自定义doclet在Javadoc中公开其他信息。我也不相信完全依赖Javadocs是最好的解决方案。
答案 2 :(得分:0)
两者都做:基类将具有返回构造函数中初始化的字段值的默认实现。子类可以覆盖getter并添加自己的逻辑。我认为为每个类实例存储字符串"txt"
所需的内存问题是无关紧要的:即使它是在子类中进行硬编码,也必须存储它。我个人并不关心6个额外的字节。
答案 3 :(得分:0)
尽量避免混合使用无状态和有状态代码。我的建议是将实现拆分为两个并行的类树。一个包含静态元数据(如文件扩展名),另一个包含使用元数据配置的工作对象。
这会为您提供一个ZipFileType
单例,您可以在ZipFileFormat
的所有实例中使用它。