我想设计一个允许用户从文件类型列表中选择以保存文件的系统。我有一个名为Word的类,以及一个名为SaveFileType的接口。每个文件类型都实现了SaveFileType,它具有saveFile()方法。这个想法是,当程序员'想要添加新的文件类型,不必更改应用程序中的任何代码。
我面临的问题是Word类没有我需要向用户显示的所有可用文件类型的列表。
以下示例代码:
词类:
public class Word {
SaveFileAs saveFileAs;
Document currentDocument;
public Word(Document currentDocument) {
this.currentDocument = currentDocument;
}
public void saveFile() {
// Print all available filetypes
// No actual file-saving logic is needed.
}
}
Word97课程:
public class Word97 implements SaveFileAs {
@Override
public void saveFile(Document currentDocument) {
// Do some Java wizardry here.
System.out.println("Document named '" + currentDocument.getTitle() + "' has been saved as filetype 'Word97' " );
}
}
主要课程:
public class Main {
public static void main(String[] args) {
Document notes = new Document("Notes", "This is a note.");
Word wordProgram = new Word(notes);
// saveFile should print out a list of all possible filetypes.
wordProgram.saveFile();
}
}
答案 0 :(得分:0)
如果Word
类知道所有类型,那将是不好的。即使单词使用它,它也是另一个类的工作。一种解决方案是创建一个将字符串扩展名映射到策略的新类。并且可以列举这些策略:
public final class DocumentTypeMap implements Iterable<SaveFileAs> {
private final Map<String, SaveFileAs> docTypes = new HashMap<>;
public void register(String extension, SaveFileAs saveFileAs) {
docTypes.put(extension, saveFileAs);
}
public Iterator<SaveFileAs> iterator() {
return docTypes.values().iterator();
}
}
用法:
DocumentTypeMap map = new DocumentTypeMap();
map.register(".doc", new Word97()); //etc.
Word word = new Word(map); //inject the dependency of a pre-configured map into the word class.
然后,当Word
类在保存期间需要正确的策略时,它可以使用DocumentTypeMap
上的方法(此处未提供)来获取正确的策略。我想这可能是延伸。
答案 1 :(得分:0)
策略是在运行时更改实现,您无法获得所有实现。这将是另一个班级的任务。你还需要在setStrategy(Strategy)
课程中以某种方式使用Word
这样的方法,这就是为什么你选择了正确的模式?
要获得所有实现,您可以使用ServiceLoader
。我想在图片中添加一个枚举。
所以示例代码如下:
Word
类中的方法:
void setSaveFileStrategy(AvailableStrategy strategy){
this.saveFileAs = strategy.strategy();
}
枚举:
enum AvailableStrategy{
Word97( Word97.class),
//.... once new strategy was introduced, you need add an entry here.
WordXml( WordXml.class);
private Class<saveFileAs> strategyClass;
AvailableStrategies(Class<saveFileAs> strategyClass) {
this.strategyClass = strategyClass;
}
saveFileAs strategy() throws IllegalAccessException, InstantiationException {
return strategyClass.newInstance() ;
}
}
我想您知道如何获取所有枚举实例(可用策略)。
请注意,代码未经过编译和测试,只是为了展示这个想法。异常处理被忽略了。
答案 2 :(得分:0)
如果您希望能够在不更改任何代码的情况下添加文档类型,则意味着必须在代码之外定义文档类型列表,在文件中定义属性文件,并且您的代码必须读取属性文件了解所有可用的类型。
然后,您需要在此属性文件中添加哪个类实现如何保存特定文档类型,并实现一个工厂,该工厂实例化一个给定其名称的类,以及一个根据所选类型关联右侧实例的类。
对于属性文件,您可以输入以下条目:
ext_1 = .DOC
ext_2 = .XML
ext_3 = .RTF
class_1 = Word97的
class_2 = WordXML
class_3 = RTF ...
这样的文件很容易解析,以便知道类型列表以及必须使用哪个类来保存文档。
要了解如何从名称中实例化类,请参阅类Class
和方法newInstance
。
这是一种“老方式”,也许注射是最新的解决方案。
在你的UML模型中,我将添加读取属性文件的类,从其名称实例化类的类,以及将右实例与Word相关联的类。要对属性文件建模,可能会使用实例objet,因为属性文件是ResourceBundle的一个实例。