AbstractFactory:kotlin

気を付けたこと

  • kotlinでは複数クラスを一つのファイルにまとめることが出来るのでまとめた
  • コンストラクタの引数宣言部分でフィールドを定義して初期化できる
  • “${式}”で文字列リテラルに式や変数を直接書き込める
  • [packageprivate]は無いので代わりに[internal]を使う

パッケージ

kotlinでは「packageprivate」のアクセス修飾子は無いです。代わりに「internal」があります。同じモジュールからのみアクセスできます。別にモジュールに分けなくてもpackageキーワードは使えますが、internalを使えるので分けといた方が良い気がします。あとjavaのようにフォルダ名とパッケージ名が一致している必要は無いみたいですが、javaと合わせておいた方が良い気がします。こちらが参考になりました。

Intellijでモジュールを追加する

追加したいフォルダを右クリックして新規➡モジュール。

ダイアログに従ってモジュール名を決めて作成する。

モジュールの依存関係を追加する

使用する側のクラスが含まれるフォルダを選択してf4キー(ファイル➡モジュールを追加)を押下。

依存関係タブの+ボタンを押して追加したいモジュールを選択。


main.kt

import factory.*
import java.io.FileWriter
import java.io.IOException
import java.io.PrintWriter
import kotlin.system.exitProcess

fun main(args:Array<String>) {
    if(args.size != 1){
        println("Usage:java main classname.of.concretaeFactory")
        println("exa1:java main listfactory.ListFactory")
        println("exa2:java main tablefactory.TableFactory")
    }
    val factory = getFactory(args[0])
    val asahi = factory.createLink("朝日新聞","http://www.asahi.com/")
    val yomiuri = factory.createLink("Yahoo", "http://www.yahoo.com/")
    val us_yahoo = factory.createLink("Yahoo!Japan","http://www.yahoo.co.us/")
    val jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/")
    val excite = factory.createLink("Excite", "http://www.excite.com/")
    val google = factory.createLink("Google", "http://www.google.com")

    val traynews = factory.createTray("新聞")
    traynews.add(asahi)
    traynews.add(yomiuri)

    val trayyahoo = factory.createTray("Yahoo")
    trayyahoo.add(us_yahoo)
    trayyahoo.add(jp_yahoo)

    val traysearch = factory.createTray("サーチエンジン")
    traysearch.add(trayyahoo)
    traysearch.add(excite)
    traysearch.add(google)

    val page = factory.createPage("LinkPage", "結城浩")
    page.add(traynews)
    page.add(traysearch)
    page.output()
}

ListFactory.kt

package listfactory
import factory.*

class ListFactory():Factory(){
    override fun createLink(caption: String, url: String): Link =
            ListLink(caption,url)

    override fun createTray(caption: String): Tray =
            ListTray(caption)

    override fun createPage(title: String, author: String): Page =
            ListPage(title,author)
}
class ListLink(caption:String,url:String):Link(caption,url){
    override fun makeHTML() =
    """
        <li><a href="$url">${caption}</a><li>
        
    """.trimIndent()
}
class ListTray(caption:String):Tray(caption){
    override fun makeHTML(): String {
        val buffer = StringBuffer()
        buffer.append("<li>\n")
        buffer.append("${caption}\n")
        buffer.append("<ul>\n")
        val it = tray.iterator()
        while (it.hasNext()) {
            val itemm = it.next() as Item
            buffer.append(itemm.makeHTML())
        }
        buffer.append("</ul>\n")
        buffer.append("</li>\n")
        return buffer.toString()
    }
}
class ListPage(title: String, author: String) : Page(title, author) {
    override fun makeHTML(): String {
        val buffer = StringBuffer()
        buffer.append("<html><head>title>${title}</title></head>\n")
        buffer.append("<body>\n")
        buffer.append("<h1>${title}</h1>\n")
        buffer.append("<ul>\n")
        val it = content.iterator()
        while (it.hasNext()) {
            val item = it.next() as Item
            buffer.append(item.makeHTML())
        }
        buffer.append("</ul>\n")
        buffer.append("<hr><address>${author}</address>")
        buffer.append("</body></html>\n")
        return buffer.toString()
    }
}

TableFactory.kt

package tablefactory
import factory.*
import javax.naming.ContextNotEmptyException

class TableFactory:Factory(){
    override fun createLink(caption: String, url: String): Link =
            TableLink(caption,url)

    override fun createPage(title: String, author: String): Page =
            TablePage(title,author)

    override fun createTray(caption: String): Tray =
            TableTray(caption)
}
class TableLink(caption: String, url: String) : Link(caption, url) {
    override fun makeHTML(): String =
            "<td><a href=\"${url}\">${caption}</a></td>\n"
}
class TableTray(caption: String):Tray(caption){
    override fun makeHTML(): String {
        val buffer = StringBuffer()
        buffer.append("<td>")
        buffer.append("<table width=\"100%\" border=\"1\"><tr>")
        buffer.append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"${tray.size}\"><b>${caption}</b></td>")
        buffer.append("</tr>\n")
        buffer.append("<tr>\n")
        val it = tray.iterator()
        while (it.hasNext()) {
            val item = it.next()as Item
            buffer.append(item.makeHTML())
        }
        buffer.append("</tr></table>")
        buffer.append("</td>")
        return buffer.toString()
    }
}
class TablePage(title: String, author: String) : Page(title, author) {
    override fun makeHTML(): String {
        val buffer = StringBuffer()
        buffer.append("<html><head><title>${title}</title></head>\n")
        buffer.append("<body>")
        buffer.append("<h1>${title}</h1>\n")
        buffer.append("<table width=\"80%\" border=\"3\">\n")
        val it = content.iterator()
        while (it.hasNext()) {
            val item = it.next() as Item
            buffer.append("<tr>${item.makeHTML()}</tr>")
        }
        buffer.append("</table>\n")
        buffer.append("<hr><address>${author}</address>")
        buffer.append("</body></html>\n")
        return buffer.toString()
    }

}

factory.kt

package factory
import listfactory.ListFactory
import java.io.FileWriter
import java.io.IOException
import java.lang.ClassCastException
import java.lang.Exception
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.superclasses
import kotlin.reflect.typeOf

abstract class Item(protected val caption: String){
    abstract fun makeHTML():String
}
abstract class Link(protected val url:String, caption: String):Item(caption){
}
abstract class Tray(caption:String):Item(caption){
    protected val tray = ArrayList<Any>()
    fun add(item: Item) = tray.add(item)
}
abstract class Page(protected val title:String,protected val author:String){
    protected val content  = ArrayList<Any>()
    fun add(item: Item):Unit { content.add(item)}
    fun output(){
        try {
            val filename = "${title}.html"
            val writer = FileWriter(filename)
            writer.write(this.makeHTML())
            writer.close()
            println("${filename}を作成しました")
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }
    abstract fun makeHTML():String
}
fun getFactory(classname:String):Factory {
    try {
        val returnClass = Class.forName(classname).kotlin.createInstance()
        return (returnClass as Factory)
    } catch (e: ClassNotFoundException) {
        throw ClassNotFoundException("クラス${classname}がみつかりません。")
    } catch (e: Exception) {
        throw e
    }
    throw Exception()
}
abstract class Factory{
    abstract fun createLink(caption:String,url:String):Link
    abstract fun createTray(caption: String):Tray
    abstract fun createPage(title:String,author:String):Page
}

元のコードは以下の本からの引用です。サンプルコードは著者さんのサイトで配布されています。リンクはAmazonアソシエイトを使用しています。

増補改訂版Java言語で学ぶデザインパターン入門

ライセンス表記

Copyright (C) 2001,2004 Hiroshi Yuki.

hyuki@hyuki.com
This software is provided ‘as-is’, without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

コメント

タイトルとURLをコピーしました