繁体   English   中英

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

[英]How to get a list of all implemented classes in Strategy Pattern?

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

这是我制作的UML图: UML图

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

如果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上的方法(此处未提供)来获取正确的策略。 我想这可能是延伸的。

策略是在运行时更改实现,您无法获得所有实现。 这将是另一个班级的任务。 你还需要在Word类中以某种方式使用setStrategy(Strategy)这样的方法,这就是为什么你选择了正确的模式?

要获得所有实现,您可以使用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() ;
        }

    }

我想你知道如何获得所有枚举实例(可用的策略)。

请注意,代码未经过编译和测试,仅用于显示想法。 异常处理被忽略了。

如果您希望能够在不更改任何代码的情况下添加文档类型,则意味着必须在代码之外定义文档类型列表,在文件中定义属性文件,并且您的代码必须读取属性文件以了解所有可用文件类型。

然后,您需要在此属性文件中添加哪个类实现如何保存特定文档类型,并实现一个实例化给定其名称的类的工厂,以及根据所选类型关联右实例的类。

对于属性文件,您可以使用以下条目:

ext_1 = .DOC

ext_2 = .XML

ext_3 = .RTF

class_1 = Word97的

class_2 = WordXML

class_3 = RTF ......

这样的文件很容易解析,以便知道类型列表以及必须使用哪个类来保存文档。 要了解如何从其名称实例化类,请参阅类Class和方法newInstance

这是一种“老方式”,也许注射是最新的解决方案。

在你的UML模型中,我将添加读取属性文件的类,从其名称实例化类的类,以及将右实例与Word相关联的类。 要对属性文件建模,可能会使用实例objet,因为属性文件是ResourceBundle的一个实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM