[Go言語]Prototypeパターンを学ぼう!

こんにちは、KOUKIです。

この記事では、デザインパターンの一つであるPrototypeパターンについて、紹介しています。

Prototypeパターンは、インスタンスのコピーや使い回しに関係するパターンです。

デザインパターンまとめ

Deep Copy

インスタンスをコピーする方法を学びましょう。

シチュエーション

インスタンスのコピーには、細心の注意を払うべきです。プロパティがポインタを持っている場合は、特にです

iPhone構造体を定義します。

この構造体からiPhoneXインスタンスを作成します。

うまくいきましたね。

次に、iPhoneXからiPhone11を作成しましょう。

簡単ですね…と言いたいところですが、この実装には以下のバグが発生します。

iphoneXのFeatureがiphone11のFeatureに書き換わっています

Featureプロパティはポインタ(*)を使っているので、コピーした時に、コピー元と同じアドレスがiphone11にも渡されるので、値が上書きされてしまいます。

このようなバグは、現場でも発生します。そして、重大なバグになりやすいです。

新しいアドレスをセットする

正しくコピーするためには、コピー後に新しいアドレスで上書きします。

OKですね。

しかし、ちょっとわかりずらいですよね。

メソッドにする

先ほどのサンプルをメソッドを使った実装に書き換えてみましょう。

まず、コピー用のメソッドを用意します。

Featureプロパティをこのメソッドを使って設定しましょう。

いくらかスッキリしましたね。

スライスのコピーにも注意が必要

インスタンスと同様にスライスをコピーする時も気をつけなければなりません。

例えば、こんな処理があったとします。

string型のスライスを用意しました。
s2にはs1の情報をコピーしており、「s2[0]=”three”」で元々の値を書き換えています

この場合、結果は次のようになります。

なんとs1の値まで書き変わってしまうのです!

スライスは、参照渡し(アドレスを渡す)で処理されるので上記のようになります。そして、これはバグを発生させます。

そのため、スライスを含むインスタンスをコピーする用途がある場合、DeepCopyメソッドを用意した方が良いと思います。

例えば、iPhoneにアプリケーション保存領域を追加しましょう。

次に、iPhoneにDeepCopyメソッドを用意します。

ここでは、ついでにFeatureプロパティのDeepCopyも呼び出しました。

copy関数はGo言語に最初から組み込まれているもので、スライスをコピーすることができます。

早速、使ってみましょう。

iPhonXのAppsが「[google map]」、iPhone11のAppsが「[google map YouTube]」になっているので、Deep Copyは成功ですね。

シリアライズ化(Encode/Decode)

先ほどは、インスタンスのアドレスを書き換えることで、DeepCopyを実現しました。それ以外にもシリアライズ化(Encode/Decode)をすることで、同様の処理を実装することも可能です。

呼び出し側の変更は、不要です。

プロトタイプ関数

iphoneXやiphon11のパラメータは手動で設定しましたが、これを関数で設定できるようにしましょう。

最初に、iPhoneXとiPhone11の基本パラメータを変数で定義します。

名前(Name)と容量(Volume)を自分で設定できるようにしました。

次に、DeepCopyメソッドを用意します。

続いて、コンストラクタ関数を定義します。

このコンストラクタ関数は内部用なので、プロトタイプ関数から呼び出します。

newIPhone関数に渡すプロトタイプによって、生成するインスタンスを制御しています

ここまでで、実装は完了です。早速使ってみましょう。

今までの実装と比べて、呼び出し処理がシンプルになりましたね。

まとめ

デザインパターンを学ぶとプログラミングの実装が、うまくなっていく感覚があります。

それは、今まで複雑に組んでしまっていたコードを、よりシンプルに実装できるようになったからだと思います。

何でもかんでもパターンに当てはめる、ということをするつもりはありませんが、実装の過程で「このパターンで実装したら面白そう!」など出てくると思うので、その場合は、使っていこうと思います。

それでは、また!

Go言語まとめ

ソースコード

Deep Copying

Deep Copy Method

Encode/Decode

Prototype

コメントを残す