CFMLでデザインパターン実装(2.Builder)

新しい言語は。。。やっぱPythonか?と言いつつ溜まっていたネタを。

今回はBuilderの実装をしてみました。実は今回はcfinterfaceの使い道を考えるというテーマがあったので、前回よりじっくりやってみました。が。。。はてさて、やはり微妙でした。


ともあれ、例によってまずはJava実装から。

まず、基本となる機能をJavaで実装したもの。

Java-1:呼び元(TestCaseをそのままmain扱い)

package creational_patterns.builder;

import junit.framework.TestCase;

public class _MainTestCase extends TestCase {
	public void test() {
		try {
			Builder builder = null;
			String word = null;

			builder = new HelloWorldBuilder();
			word = this.getSaid(builder);
			System.out.println(word);
			builder = new GoodByWorldBuilder();
			word = this.getSaid(builder);
			System.out.println(word);
		} catch (Exception e) {
			e.printStackTrace();
			fail();
		}
	}
	private String getSaid(Builder builderInstance) {
		Director director = new Director(builderInstance);
		director.constract();
		return builderInstance.getWord();
	}
}

Java-2:Interface Builder

package creational_patterns.builder;

public interface Builder {
	public void setWord(String word);
	public String getWord();
}

Java-3:Director

package creational_patterns.builder;

public class Director {
	private Builder builder;
	public Director(Builder builder) {
		this.builder = builder;
	}
	public void constract() {
		this.builder.setWord("Hello, Builder pattern.");
	}
}

Java-4:Concrete builder(HelloWorldBuilder)

package creational_patterns.builder;

import common.HelloWorld;

public class HelloWorldBuilder implements Builder {
	private HelloWorld helloWorld;
	public HelloWorldBuilder() {
		this.helloWorld = new HelloWorld();
	}
	@Override
	public String getWord() {
		return this.helloWorld.say();
	}
	@Override
	public void setWord(String word) {
		this.helloWorld.setWord(word);
	}
}

以上がJavaソースコードです。(実はもう1つ、GoodByWorldBuilderが存在していますが、Directorでパラメータをべた書きしている為、ここに掲載する意味もない実装する意味もないので省略です)これを実行すると、

Hello, Builder pattern.

が出てきます。

これに続いて、

このJavaコードをまんまCFMLに展開。

cf-1:呼び元(ブラウザで見るしかないのでCFMで実装)

<html>
	<head>
		<title>Gof design pattern@CFML</title>
	</head>
	<body>
		<cfoutput>
			<cftry>
				<h5>Builder</h5>
				<cfobject name="Variables.builder" component="cftest.gof.builder.HelloWorldBuilder"/>
				<cfinvoke component="#Variables.builder#" method="HelloWorldBuilder"/>
				<cfinvoke component="cftest.gof.builder.Director" method="Director">
					<cfinvokeargument name="builder" value="#Variables.builder#"/>
				</cfinvoke>
				<cfset Variables.s=Variables.builder.getWord()/>
				HelloWorldBuilder:[#Variables.s#]<br/>
				<hr/>
				<cfobject name="Variables.builder" component="cftest.gof.builder.GoodByWorldBuilder"/>
				<cfinvoke component="#Variables.builder#" method="GoodByWorldBuilder"/>
				<cfinvoke component="cftest.gof.builder.Director" method="Director">
					<cfinvokeargument name="builder" value="#Variables.builder#"/>
				</cfinvoke>
				<cfset Variables.s=Variables.builder.getWord()/>
				HelloWorldBuilder:[#Variables.s#]<br/>
				<cfcatch>
					<cfdump var="#cfcatch#"/>
				</cfcatch>
			</cftry>
		</cfoutput>
	</body>
</html>

cf-2:Builder

<cfinterface>

	<cffunction name="setWord" access="public" returntype="void">
		<cfargument name="word" type="string" required="true"/>
	</cffunction>

	<cffunction name="getWord" access="public" returntype="string"/>

</cfinterface>

cf-3:Director

<cfcomponent output="false">

	<cffunction name="Director" access="public" returntype="void">
		<cfargument name="builder" type="cftest.gof.builder.Builder" required="true"/>
		<cfset This.builder=Arguments.builder/>
	</cffunction>

	<cffunction name="constract" access="public" returntype="void">
		<cfinvoke component="#This.builder#" method="setWord">
			<cfinvokeargument name="word" value="Hello, Builder pattern."/>
		</cfinvoke>
	</cffunction>

</cfcomponent>

cf-4:Concrete builder(HelloWorldBuilder)

<cfcomponent implements="cftest.gof.builder.Builder" output="false">

	<!---// コンストラクタ風 //--->
	<cffunction name="HelloWorldBuilder" access="public" returntype="cftest.gof.common.HelloWorld">
		<cfobject name="This.helloWorld" component="cftest.gof.common.HelloWorld"/>
		<cfinvoke component="#This.helloWorld#" method="HelloWorld"/>
		<cfreturn This.helloWorld/>
	</cffunction>

	<cffunction name="setWord" access="public" returntype="void">
		<cfargument name="word" type="string" required="true"/>
		<cfinvoke component="#This.helloWorld#" method="setWord">
			<cfinvokeargument name="word" value="#Arguments.word#"/>
		</cfinvoke>
	</cffunction>

	<cffunction name="getWord" access="public" returntype="string">
		<cfset var retVal=""/>
		<cfinvoke component="#This.helloWorld#" method="getWord" returnvariable="retVal">
		<cfreturn retVal/>
	</cffunction>
</cfcomponent>

で、実行すると、

HelloWorldBuilder:[Hello, World.]

こんな感じ。