概要
GoFのデザインパターンのAbstractFactoryパターンについて。
Factoryで利用するオブジェクト一式をまとめて入れ替えることが可能です。
登場人物
AbstractFactory = 工場の抽象クラス
ConcreteAbstractFactory = 工場の具象クラス
AbstractProduct = 製品の抽象クラス
ConcreteAbstractProduct = 製品の具象クラス
実装サンプル
サンプル概要
ある言語のソースコードを生成するプログラムを想定します。
ソースコードを生成するための工場がLanguageFactory。
Ruby用に実装した工場がRubyFactory。
Java用に実装した工場がJavaFactory。
工場から生成される製品がSourceCode。
Ruby用に実装した製品がRubySourceCode。
Java用に実装した製品がJavaSourceCode。
LanguageFactoryに具体的なFactory名を渡し、任意の言語のFactoryを取得したら
create_languageメソッドでクラス名を設定したソースコード生成オブジェクトを取得します。
取得したオブジェクトに対してcreate_fieldでフィールドを設定、create_methodでメソッドを設定し、
get_sourcecodeメソッドを実行すれば自分が指定したクラス名・フィールドリスト・メソッドリストで
ソースコードを出力します。
登場人物
AbstractFactory = LanguageFactory : 言語工場の抽象クラス
ConcreteAbstractFactory = RubyFactory : Ruby工場の具象クラス
ConcreteAbstractFactory = JavaFactory : Java工場の具象クラス
AbstractProduct = SourceCode : 言語の抽象クラス
ConcreteAbstractProduct = RubySourceCode : Ruby言語の具象クラス
ConcreteAbstractProduct = JavaSourceCode : Java言語の抽象クラス
AbstractProduct = Method : メソッドの抽象クラス
ConcreteAbstractProduct = RubyMethod : Rubyメソッドの具象クラス
ConcreteAbstractProduct = JavaMethod : Javaメソッドの具象クラス
AbstractProduct = Field : フィールドの抽象クラス
ConcreteAbstractProduct = RubyField : Rubyフィールドの具象クラス
ConcreteAbstractProduct = JavaField : Javaフィールドの具象クラス
サンプルコード
LanguageFactory
# encoding: Shift_JIS =begin rdoc = LanguageFactoryクラス =end class LanguageFactory NOT_OVERRRIDE = 'not override error' NOT_EXIST_CLASS = 'not exist class' def self.get_factory(language) factory = Object.const_get(language).new return factory rescue NameError raise LanguageFactory::NOT_EXIST_CLASS end def create_language(class_name) raise LanguageFactory::NOT_OVERRRIDE end def create_method(access_modifier,return_type,method_name,param_list_map) raise LanguageFactory::NOT_OVERRRIDE end def create_field(access_modifier,type,field_name,default_value) raise LanguageFactory::NOT_OVERRRIDE end end
RubyFactory
# encoding: Shift_JIS require_relative './language_factory' require_relative './ruby_sourcecode' require_relative './ruby_method' require_relative './ruby_field' =begin rdoc = RubyFactoryクラス =end class RubyFactory < LanguageFactory def create_language(class_name) ruby_source = RubySourcecode.new(class_name) return ruby_source end def create_method(access_modifier,return_type,method_name,param_list_map) ruby_method = RubyMethod.new() ruby_method.method_name = method_name ruby_method.access_modifier = access_modifier ruby_method.param_list_map = param_list_map return ruby_method end def create_field(access_modifier,type,field_name,default_value) ruby_field = RubyField.new() ruby_field.field_name = field_name ruby_field.access_modifier = access_modifier ruby_field.default_value = default_value return ruby_field end end
JavaFactory
# encoding: Shift_JIS require_relative './language_factory' require_relative './java_sourcecode' require_relative './java_method' require_relative './java_field' =begin rdoc = JavaFactoryクラス =end class JavaFactory < LanguageFactory def create_language(class_name) java_source = JavaSourcecode.new(class_name) return java_source end def create_method(access_modifier,return_type,method_name,param_list_map) java_method = JavaMethod.new() java_method.method_name = method_name java_method.return_type = return_type java_method.access_modifier = access_modifier java_method.param_list_map = param_list_map return java_method end def create_field(access_modifier,type,field_name,default_value) java_field = JavaField.new() java_field.field_name = field_name java_field.access_modifier = access_modifier java_field.default_value = default_value return java_field end end
SourceCode
# encoding: Shift_JIS require_relative './method_' require_relative './field' =begin rdoc = Sourcecodeクラス =end class Sourcecode NOT_OVERRRIDE = 'not override error' attr_accessor :class_name,:field_list,:method_list def initialize(class_name) @class_name = class_name end def get_class_start() raise Sourcecode::NOT_OVERRRIDE end def get_class_end() raise Sourcecode::NOT_OVERRRIDE end def get_class_sourcecode() raise Sourcecode::NOT_OVERRRIDE end def get_mothod_sourcecode() raise Sourcecode::NOT_OVERRRIDE end def get_field_sourcecode() raise Sourcecode::NOT_OVERRRIDE end def get_sourcecode() raise Sourcecode::NOT_OVERRRIDE end end
RubySourceCode
# encoding: Shift_JIS require_relative './sourcecode' =begin rdoc = RubySourcecodeクラス =end class RubySourcecode < Sourcecode def get_class_start() return "" end def get_class_end() return "end" end def get_class_sourcecode() return "class #{@class_name}" end def get_method_sourcecode() methods_ = "" @method_list.each {|method_| methods_ += "\tdef #{method_.method_name}(" unless method_.param_list_map.nil? method_.param_list_map.each {|method_param| methods_ += "#{method_param['param_name']}," } #右端の1文字を削除すること methods_ = methods_.slice(0,methods_.size-1) end methods_ += ")\n\n\tend\n\n" } return methods_ end def get_field_sourcecode() fields = "" @field_list.each {|field| fields << "\t" + field.field_name if field.default_value.nil? fields << "\n" else fields << " = \'#{field.default_value}\'\n" end } return fields end def get_sourcecode() puts get_class_sourcecode puts get_field_sourcecode puts "" puts get_method_sourcecode puts get_class_end end end
JavaSourceCode
# encoding: Shift_JIS require_relative './sourcecode' =begin rdoc = JavaSourcecodeクラス =end class JavaSourcecode < Sourcecode VOID = "void" def get_class_start() return " {" end def get_class_end() return "}" end def get_class_sourcecode() return "public class #{@class_name}" end def get_method_sourcecode() methods_ = "" @method_list.each {|method_| if method_.access_modifier.nil? || method_.access_modifier.empty? methods_ << "\t" else methods_ << "\t#{method_.access_modifier} " end if method_.return_type.nil? methods_ << JavaSourcecode::VOID else methods_ << method_.return_type end methods_ += " #{method_.method_name}(" unless method_.param_list_map.nil? method_.param_list_map.each {|method_param| methods_ += "#{method_param['param_type']} " methods_ += "#{method_param['param_name']}," } #右端の1文字を削除すること methods_ = methods_.slice(0,methods_.size-1) end methods_ += ") {\n\n\t}\n\n" } return methods_ end def get_field_sourcecode() fields = "" @field_list.each {|field| fields << "\t" unless field.access_modifier.nil? || field.access_modifier.empty? fields << field.access_modifier + " " end fields << field.field_name unless field.default_value.nil? fields << " = #{field.default_value}" end fields << ";\n" } return fields end def get_sourcecode() print get_class_sourcecode puts get_class_start puts get_field_sourcecode puts "" puts get_method_sourcecode puts get_class_end end end
Method
# encoding: Shift_JIS =begin rdoc = Methodクラス =end class Method_ attr_accessor :method_name,:return_type,:access_modifier,:param_list_map def initialize(method_name) @method_name = method_name end end
RubyMethod
※今回はクラス内の拡張はなし。継承しただけ
JavaMethod
※今回はクラス内の拡張はなし。継承しただけ
Field
# encoding: Shift_JIS =begin rdoc = Fieldクラス =end class Field attr_accessor :field_name,:access_modifier,:default_value def initialize(field_name) @field_name = field_name end end
RubyField
※今回はクラス内の拡張はなし。継承しただけ
JavaField
※今回はクラス内の拡張はなし。継承しただけ
main処理
# encoding: Shift_JIS require_relative './language_factory' require_relative './sourcecode' require_relative './ruby_factory' require_relative './ruby_sourcecode' require_relative './java_factory' require_relative './java_sourcecode' lang_factory = LanguageFactory.get_factory('RubyFactory') # class名の設定 ruby_source = lang_factory.create_language 'SampleRubyClass' # フィールドの設定 field1 = RubyField.new('@sample_ruby_field1') field1.access_modifier = nil field1.default_value = nil field2 = RubyField.new('@sample_ruby_field2') field2.access_modifier = nil field2.default_value = 'default' field_list = [field1,field2] ruby_source.field_list = field_list # メソッドの設定 method1 = RubyMethod.new('sample_ruby_method1') method1.return_type = "String" method1.access_modifier = "private" method1.param_list_map = nil method2 = RubyMethod.new('sample_ruby_method2') method2.return_type = nil method1.access_modifier = "public" param_map2_1 = {"param_name" => "param1", "param_type" => "Map"} param_map2_2 = {"param_name" => "param2", "param_type" => "List"} param_list = [param_map2_1, param_map2_2] method2.param_list_map = param_list method_list = [method1,method2] ruby_source.method_list = method_list puts ruby_source.get_sourcecode puts "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−" lang_factory = LanguageFactory.get_factory('JavaFactory') # class名の設定 java_source = lang_factory.create_language 'SampleJavaClass' # フィールドの設定 field1 = JavaField.new('sampleJavaField1') field1.access_modifier = "int" field1.default_value = nil field2 = JavaField.new('sampleJavaField2') field2.access_modifier = "String" field2.default_value = "\"default\"" field3 = JavaField.new('sampleJavaField3') field3.access_modifier = nil field3.default_value = nil field_list = [field1,field2,field3] java_source.field_list = field_list # メソッドの設定 method1 = JavaMethod.new('sample_java_method1') method1.return_type = "String" method1.access_modifier = "private" method1.param_list_map = nil method2 = JavaMethod.new('sample_java_method2') method2.return_type = nil method1.access_modifier = "public" param_map2_1 = {"param_name" => "param1", "param_type" => "Map"} param_map2_2 = {"param_name" => "param2", "param_type" => "List"} param_list = [param_map2_1, param_map2_2] method2.param_list_map = param_list method_list = [method1,method2] java_source.method_list = method_list puts java_source.get_sourcecode
出力
class SampleRubyClass @sample_ruby_field1 @sample_ruby_field2 = 'default' def sample_ruby_method1() end def sample_ruby_method2(param1,param2) end end −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− public class SampleJavaClass { int sampleJavaField1; String sampleJavaField2 = "default"; sampleJavaField3; public String sample_java_method1() { } void sample_java_method2(Map param1,List param2) { } }