NimでFactoryパターンを実装する

概要

以前からfactory(又はstrategy)をNimで実装できないかということを、ちょこちょこ調べていた。

今回、実装に成功したので、そのことを以下に記載する。

環境

Nim Compiler Version 1.4.0 [Linux: amd64]

ソースコード

github.com

ソースコードの説明

以下にソースコードの説明を記載していく。

1行目~2行目

type AnimalKind {.pure.} = enum
  DOG, CAT, BIRD

あとでFactoryのcreate部分で使うAnimalKindという名前のenumを定義。

pragmaの一種である{.pure.}をつけることによって必ずAnimalKind.DOGといった形で呼び出さなければならなくなる。

(DOG単体で呼び出そうとするとエラーになる)

o AnimalKind.DOG
x DOG

4行目~6行目

type Animal = ref object of RootObj
  name: string
  kind: AnimalKind

継承元のオブエジェクトを作成する。

プロパティは2つでありnameをstring型, kindをAnimalKind型で定義。

objectだとヒープ領域に作られずに動的にできないのでref objectにしている。

ref objectにしないとFactoryでcreate出来なくなるので注意。

恐らくコンパイルは通っても実行でエラーになるだろう。

8行目

method getKind(animal: Animal): string {.base.} = "ANIMAL"

先程定義したAnimalにBaseとなるmethodを定義する。

今回は分かりやすくgetKindと叩かれると何かしらの文字列が帰ってくるだけというシンプルなmethodにした。

nimには他にもprocやfuncといった関数の定義方法があるが オブジェクト思考で実装する場合は、methodを使う。

(procとfuncは手続き型で使ってfuncは副作用を許さない固い関数を定義出来る)

10行目~17行目

type Dog = ref object of Animal
method getKind(dog: Dog): string = "DOG"

type Cat = ref object of Animal
method getKind(cat: Cat): string = "CAT"

type Bird = ref object of Animal
method getKind(bird: Bird): string = "BIRD"

ref object of XXXで継承する。

Animalを継承したDog、Cat、Birdクラスを定義し、それぞれ別の文字列が帰ってくるgetKindメソッドを定義する。

19行目~24行目

type AnimalFactory = object
func create*(factory: AnimalFactory, kind: AnimalKind): Animal = 
  case kind
    of AnimalKind.DOG: return Dog(name: "xxx", kind: kind)
    of AnimalKind.CAT: return Cat(name: "ooo", kind: kind)
    of AnimalKind.BIRD: return Bird(name: "iii", kind: kind)

今回の目的であるAnimalを作成するAnimalFactoryを実装。

ヒープ領域を使う必要がないのでobjectで定義。

アスタリスク(*)をつけることで外から、この関数を叩けるようになる。

戻り値の型をAnimalにすることにより、Animalを継承しているDog, Cat, Birdが返却できるようになる。

26行目~35行目

let factory = AnimalFactory()

let dog = factory.create(AnimalKind.DOG)
echo dog.getKind()

let cat = factory.create(AnimalKind.CAT)
echo cat.getKind()

let bird = factory.create(AnimalKind.BIRD)
echo bird.getKind()

AnimalFactoryを実際に使用する。

タグとしてAnimalKindをわたしてdog, cat, birdを作成している。

echoで異なる結果が出力されたのなら成功。

実行結果は以下となる。

DOG
CAT
BIRD