blog

デザインパターン - ファクトリーパターン

上記のコードから、ファクトリーメソッドパターンの導入後、ファクトリークラスのオブジェクトがload()関数に結合され、設計が複雑になっていることがわかります。 単純なファクトリーとファクトリーメソッド...

Mar 15, 2020 · 4 min. read
シェア

単純なファクトリーパターン

/**
 * 
 * @create 2020-08-04 15:12
 * @description シンプル・ファクトリー・パターン
 **/
public class RuleConfigSource {
 public IRuleConfigParser load(String ruleConfigFilePath) throws Exception {
 String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
 return RuleConfigParserFactory.createParser(ruleConfigFileExtension);
 }
 private String getFileExtension(String filePath){
 return "json";
 }
}
/**
 * 
 * @create 2020-08-04 15:28
 * @description 
 **/
public class RuleConfigParserFactory {
 private static IRuleConfigParser iRuleConfigParser;
 public static IRuleConfigParser createParser(String configFormat) throws Exception {
 if("json".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new JsonRuleConfigParser();
 }else if("xml".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new XmlRuleConfigParser();
 }else if("properties".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new PropertiesRuleConfigParser();
 }else{
 throw new Exception("Rule config file format is not suported"+configFormat);
 }
 return iRuleConfigParser;
 }
}
/**
 * 
 * @create 2020-08-04 15:34
 * @description シングルトン・パターンとシンプル・ファクトリーを組み合わせる
 **/
public class RuleConfigParser1Factory {
 private static Map<String,IRuleConfigParser> cacheMap = new HashMap<>();
 static{
 cacheMap.put("json",new JsonRuleConfigParser());
 cacheMap.put("xml",new XmlRuleConfigParser());
 cacheMap.put("properties",new PropertiesRuleConfigParser());
 }
 public static IRuleConfigParser createParser(String configFormat) throws Exception {
 if(configFormat == null || configFormat.isEmpty()){
 return null;
 }
 return cacheMap.get(configFormat);
 }
}

要約すると、単純なファクトリーパターンはオープン/クローズの原則に違反していますが、可読性と拡張性のトレードオフにより、新しいパースを頻繁に追加しない限り、このようなコードも許容できるということです!

ファクトリーメソッドパターン

public interface IRuleConfigParserFactory{
	IRuleConfigParser createParser();
}
public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory{
	
	public IRuleConfigParser createParser(){
		return new JsonRuleConfigParser();
	}
}
public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory{
	
	public IRuleConfigParser createParser(){
		return new XmlRuleConfigParser();
	}
}
public class PropertiesRuleConfigParserFactory implements IRuleConfigParserFactory{
	
	public IRuleConfigParser createParser(){
		return new PropertiesRuleConfigParser();
	}
}
/**
 * 
 * @create 2020-08-04 15:12
 * @description ファクトリー・メソッド・パターン
 **/
public class RuleConfigSource {
	private IRuleConfigParser iRuleConfigParser;
 public IRuleConfigParser load(String ruleConfigFilePath) throws Exception {
 String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
 if("json".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new JsonRuleConfigParserFactory();
 }else if("xml".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new XmlRuleConfigParserFactory();
 }else if("properties".equalsIgnoreCase(configFormat)){
 iRuleConfigParser = new PropertiesRuleConfigParserFactory();
 }else{
 throw new Exception("Rule config file format is not suported"+configFormat);
 }
		return iRuleConfigParser;
 }
 private String getFileExtension(String filePath){
 return "json";
 }
}

上記のコードから、ファクトリーメソッドパターンの導入後、ファクトリークラスのオブジェクトは、設計を複雑にする代わりに、load()関数に結合されていることがわかります。

ファクトリーメソッドパターンはいつ使うべきですか?

ファクトリーメソッドを作成するために、オブジェクトを作成するロジックの一部を取り除く必要がある場合、このコードブロックのロジックが複雑すぎることが理由ですが、コードのロジック自体が複雑でなければ、分割する必要はありません。

オブジェクトの生成処理が複雑すぎて、他のクラスを組み合わせたい場合は、ファクトリーメソッドパターンを使うことをお勧めします。

抽象ファクトリーパターン

単純なファクトリーとファクトリーメソッドでは、クラスは一方向にのみ分類されます。たとえば、ルール構成の解析の例では、パーサークラスは構成ファイルの形式によってのみ分類されます。しかし、クラスが 2 通りの分類方法を持つ場合、たとえば、設定ファイルの形式または解析されるオブジェクトのいずれかによって分類される場合、次の 8 つのパーサークラスに対応します。

ルール・コンフィギュレーションのパーサー:インターフェースIRuleConfigParserに基づく。
JsonRuleConfigParser
XmlRuleConfigParser
YamlRuleConfigParser
PropertiesRuleConfigParser
システム・コンフィギュレーション用パーサー:インターフェースISystemConfigParserに基づく。
JsonSystemConfigParser
XmlSystemConfigParser
YamlSystemConfigParser
PropertiesSystemConfigParser
public interface IConfigParserFactory {
	IRuleConfigParser createRuleParser();
	ISystemConfigParser createSystemParser();
	//これは、IBizConfigParser 5のような新しいパーサ・タイプで拡張できる。 
} 
public class JsonConfigParserFactory implements IConfigParserFactory { 
	@Override
	public IRuleConfigParser createRuleParser() {
		return new JsonRuleConfigParser()
	}
	@Override
	public ISystemConfigParser createSystemParser() {
		return new JsonSystemConfigParser();
	}
}
public class XmlConfigParserFactory implements IConfigParserFactory {
	@Override
	public IRuleConfigParser createRuleParser() {
		return new XmlRuleConfigParser();
	}
	@Override
	public ISystemConfigParser createSystemParser() {
		return new XmlSystemConfigParser();
	}
} 
// YamlConfigParserFactory と PropertiesConfigParserFactory のコードは省略する。
Read next

Python3 基礎 04 辞書とコレクション

辞書はpythonのマッピングコンテナです。 文字列、値、変更不可能なタプルは辞書のキーとして使用できます。 主に、一般的な辞書メソッドを紹介します。 len: 辞書 d に含まれるキーと値のペアの数を返します。 d[key]は、...のとき、存在すれば真を、存在しなければ偽を返します。

Mar 15, 2020 · 10 min read