Golangで、デザインパターン「Adapter」を学ぶ

GoFのデザインパターンを学習する素材として、書籍「[増補改訂版Java言語で学ぶデザインパターン入門](https://www.hyuki.com/dp/)」が参考になるみたいですね。
取り上げられている実例は、JAVAベースのため、Pythonで同等のプラクティスに挑んだことがありました。
[Qiita記事: "Pythonで、デザインパターン「Adapter」を学ぶ"](https://qiita.com/ttsubo/items/d999f8dc2446c2aa30fb)

今回は、Pythonで実装した”Adapter”のサンプルアプリをGolangで実装し直してみました。

# ■ Adapter（アダプター・パターン）
Adapterパターン（アダプター・パターン）とは、GoF (Gang of Four; 4人のギャングたち) によって定義されたデザインパターンの1つである。Adapterパターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。Adapterパターンを実現するための手法として"**継承を利用した手法**"と"**委譲を利用した手法**"が存在する。

## UML class diagram
![W3sDesign_Adapter_Design_Pattern_UML.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/7e65457a-bb6b-7cff-5265-9ebfc4d4e20e.jpeg)


### 1. 継承を利用したAdapter
継承を利用したAdapterは、利用したいクラスのサブクラスを作成し、そのサブクラスに対して必要なインタフェースを実装することで実現される。
![inheritence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/d1f60174-d1e1-d620-0566-2b04ebcdf431.png)


### 2. 委譲を利用したAdapter
委譲を利用したAdapterは、利用したいクラスのインスタンスを生成し、そのインスタンスを他クラスから利用することで実現される。
![delegation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/a8943aab-6f32-c391-cbdc-c4ecebdb869a.png)
[(以上、ウィキペディア（Wikipedia）より引用)](https://ja.wikipedia.org/wiki/Adapter_パターン)

# ■ Golangで、Pythonクラスを実装し直す際の備忘録
**Golang では、Python等でお馴染みの、Inheritance（継承）ではなく、Composition（合成）のみが使われます。**

具体的、以下の２点を気をつけて、サンプルアプリの再実装に取り組みました。

- golangには、オブジェクトのクラス継承の概念が存在しないので、再利用性(Embedded)と多相性(Interface)の活用で対応する必要がある。 
- Pythonの場合だと、動的型付けのおかげて、引数／戻り値の型を意識することなくポリモーフィズムを実践できていたが、Golangの場合では、引数／戻り値の型を柔軟に扱えるようインタフェースを活用する必要がある。

## □ 大変、お世話になったQiita記事
- [Go言語で「embedded で継承ができる」と思わないほうがいいのはなぜか？](https://qiita.com/Maki-Daisuke/items/511b8989e528f7c70f80)
- [Goやるなら知っておきたい「Composition over inheritance」](https://qiita.com/kskinaba/items/903967dc8997e7d7444a)

# ■ "Adapter"のサンプルプログラム
実際に、Adapterパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。

- 文字列を、カッコでくくって表示する
- 文字列の前後に、*印をつけて表示する


なお、サンプルプログラムは、<b>再利用性(Embedded)</b>を活用したものと<b>多相性(Interface)</b>を活用したもの、それぞれ用意しました。サンプルプログラム動作の結果は、全く同じになります。


## □ 再利用性(Embedded)を利用したサンプルプログラム
```console
$ go run Adapter_1_Embedding/Main.go 
(Hello)
*Hello*
```
## □ 多相性(Interface)を利用したサンプルプログラム
```console
$ go run Adapter_2_Interface/Main.go 
(Hello)
*Hello*
```

# ■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/Adapter

- ディレクトリ構成

```console
.
├── Adapter_1_Embedding
│   ├── Main.go
│   └── adapter
│       ├── banner.go
│       └── print_banner.go
└── Adapter_2_Interface
    ├── Main.go
    └── adapter
        ├── banner.go
        └── print_banner.go
```

## □ 再利用性(Embedded)を利用したサンプルプログラム

## (1) Target（対象）の役
`Target`役は、インスタンスの振る舞いに関わるインタフェースを定めます。
再利用性(Embedded)を利用したサンプルプログラムでは、この役は存在しません。


## (2) Client（依頼者）の役
`Target`役のメソッドを使って、仕事をする役です。
サンプルプログラムでは、`startMain`メソッドが、この役を努めます。

```go:Adapter_1_Embedding/Main.go
package main

import (
	"./adapter"
)

func startMain() {
	p := adapter.NewPrintBanner("Hello")
	p.PrintWeak()
	p.PrintString()
}

func main() {
	startMain()
}
```

## (3) Adaptee（適合される側）の役
`Adapter`役のなかで実際に動作するメソッドを、ここで実装します。
サンプルプログラムでは、`banner`構造体が、この役を努めます。

```go:Adapter_1_Embedding/banner.go
package adapter

import "fmt"

type banner struct {
	str string
}

func (b *banner) showWithParen() {
	fmt.Printf("(%s)\n", b.str)
}

func (b *banner) showWithAster() {
	fmt.Printf("*%s*\n", b.str)
}
```

## (4) Adapter（適合する側）の役
`Adapter`役は、`Target`役のインタフェースを実装しているクラスです。
サンプルプログラムでは、`PrintBanner`構造体が、この役を努めます。

```go:Adapter_1_Embedding/print_banner.go
package adapter

// PrintBanner is struct
type PrintBanner struct {
	*banner
}

// NewPrintBanner func for initializing PrintBanner
func NewPrintBanner(str string) *PrintBanner {
	return &PrintBanner{
		banner: &banner{str: str},
	}
}

// PrintWeak func for formatting with paren
func (p *PrintBanner) PrintWeak() {
	p.showWithParen()
}

// PrintString func for formatting with aster
func (p *PrintBanner) PrintString() {
	p.showWithAster()
}
```

## □ 多相性(Interface)を利用したサンプルプログラム

## (1) Target（対象）の役
`Target`役は、インスタンスの振る舞いに関わるインタフェースを定めます。
多相性(Interface)を利用したサンプルプログラムでも、この役は存在しません。


## (2) Client（依頼者）の役
`Target`役のメソッドを使って、仕事をする役です。
サンプルプログラムでは、`startMain`関数が、この役を努めます。

```go:Adapter_2_Interface/Main.go
package main

import (
	"./adapter"
)

func startMain() {
	p := adapter.NewPrintBanner("Hello")
	p.PrintWeak()
	p.PrintString()
}

func main() {
	startMain()
}
```

## (3) Adaptee（適合される側）の役
`Adapter`役のなかで実際に動作するメソッドを、ここで実装します。
サンプルプログラムでは、`banner`インタフェースに、<b>Composition</b>を適用して、この役を努めます。

```go:Adapter_2_Interface/banner.go
package adapter

import "fmt"

type banner interface {
	showWithParen()
	showWithAster()
}

func (p *PrintBanner) showWithParen() {
	fmt.Printf("(%s)\n", p.str)
}

func (p *PrintBanner) showWithAster() {
	fmt.Printf("*%s*\n", p.str)
}
```

## (4) Adapter（適合する側）の役
`Adapter`役は、`Target`役のインタフェースを実装しているクラスです。
サンプルプログラムでは、`PrintBanner`構造体が、この役を努めます。

```go:Adapter_2_Interface/print_banner.go
package adapter

// PrintBanner is struct
type PrintBanner struct {
	str    string
	banner banner
}

// NewPrintBanner func for initializing PrintBanner
func NewPrintBanner(str string) *PrintBanner {
	printBanner := &PrintBanner{
		str: str,
	}
	printBanner.banner = printBanner
	return printBanner
}

// PrintWeak func for formatting with paren
func (p *PrintBanner) PrintWeak() {
	p.banner.showWithParen()
}

// PrintString func for formatting with aster
func (p *PrintBanner) PrintString() {
	p.banner.showWithAster()
}
```


# ■ 参考URL
- [Pythonで、デザインパターン「Adapter」を学ぶ](https://qiita.com/ttsubo/items/d999f8dc2446c2aa30fb)