簡體   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