Facadeパターンとは
構造に関するデザインパターンの一つ。ライブラリーやフレームワーク等の複雑なシステムに対して、その実装を利用する側から隠蔽し、シンプルなインターフェースを提供することができる。
長所
- サブシステムの複雑な実装から利用する側を分離することができる。
(サブシステムのバージョンアップ等があってもFacadeのみの修正で対応が可能になる。) - 再帰的にFacadeパターンを適用することで、複雑なシステムを再利用しやすくなる。
短所
- Facadeを適切に分割する必要がある。分割しない場合、サブシステムの多数のオブジェクトに依存した神オブジェクトになる可能性がある。
利用場面
- 複雑なサブシステムの一部機能を利用した処理を、簡潔なインターフェースをで用意したい場合。
- サブシステムを多層構造にしたい場合。(サブシステムの各レベルでのインターフェースを用意する)
クラス図

- Facade
複雑なサブシステムの高レベルでシンプルなインターフェースをシステム外部に提供する。
クライアントからのリクエストをサブシステムを利用して処理を行う。サブシステムの実装の詳細について知っている必要あり。 - Additional Facade
Facadeを再帰的に作成したり、小さな粒度で構成することによって複雑なFacadeになることを防ぐことができる。
クライアントからでもほかのFacadeからでも利用可能。 - Sub System
多数のオブジェクトからなる複雑なシステム。サブシステム内のオブジェクトはFacadeについては全く認識しない。 - サブシステムのオブジェクトを直接利用する代わりに、Facadeを利用する。
実装例
Facade
package counter
type WordCounter struct {
counter
spliter
lower
}
func NewWordCounter(sep string) *WordCounter {
return &WordCounter{
counter: counter{},
spliter: spliter{sep: sep},
lower: lower{},
}
}
// 複雑な処理を行うAPIを提供する。
// このクラスを利用することで、単語のカウントが容易に行える。
// その代わりに小文字化や文字列分割の機能は利用できない。
// →機能性とシンプルさのトレードオフ
func (c *WordCounter) Count(sentence string) map[string]int {
lower_sentence := c.lower.lower(sentence)
word_list := c.spliter.split(lower_sentence)
counts := c.counter.count(word_list)
return counts
}
Sub System
ここに記載の実装はFacadeパターンには直接関係はない。
package counter
import (
"strings"
)
type spliter struct {
sep string
}
func (s *spliter) split(sentence string) []string {
return strings.Split(sentence, s.sep)
}
package counter
import (
"strings"
)
type lower struct {}
func (l *lower) lower(sentence string) string {
return strings.ToLower(sentence)
}
package counter
type counter struct {}
func (c *counter) count(list []string) map[string]int {
m := map[string]int{}
for _, word := range list {
m[word]++
}
return m
}
動作確認
package main
import (
"fmt"
"facade/counter"
)
func main() {
// 利用する側はFacadeの背後にある複雑なサブシステムに依存しない。
// サブシステムの修正や別サブシステムへの切替の場合は、Facadeクラスの変更のみが必要になる。
wc := counter.NewWordCounter(" ")
count := wc.Count("This is a pen. This pen is so good. I like this pen.")
fmt.Println(count)
}
>> go run .
map[a:1 good.:1 i:1 is:2 like:1 pen:1 pen.:2 so:1 this:3]
コメント