如何获取策略模式中所有已实现类的列表?

时间:2016-12-14 13:50:07

标签: java uml strategy-pattern

我想设计一个允许用户从文件类型列表中选择以保存文件的系统。我有一个名为Word的类,以及一个名为SaveFileType的接口。每个文件类型都实现了SaveFileType,它具有saveFile()方法。这个想法是,当程序员'想要添加新的文件类型,不必更改应用程序中的任何代码。

这是我制作的UML图:UML Diagram

我面临的问题是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();
    }
}

3 个答案:

答案 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的一个实例。