1. ファクトリ関数=ソフトウェアの工場
ファクトリ関数はまさにプログラミング世界の「工場」です。その特徴を現実の工場と比較しながら解説します。
工場の特徴と対応関係
現実の工場 | ファクトリ関数 |
---|---|
原材料を受け取る | パラメータを受け取る |
製造工程がある | オブジェクト生成ロジック |
品質検査を行う | バリデーション処理 |
完成品を出荷 | オブジェクトを返却 |
生産ラインを隠蔽 | 実装詳細をカプセル化 |
2. ファクトリ関数の3大機能
① 生産機能(オブジェクト生成)
// 自動車工場
func CreateCar(maker string, model string) *Car {
return &Car{
Maker: maker,
Model: model,
}
}
- 原材料(パラメータ)から製品(オブジェクト)を生産
② 加工機能(データ変換)
// 車体ナンバー加工付き工場
func CreateCarWithSerial(maker string) (*Car, error) {
serial, err := generateSerial() // 加工工程
if err != nil {
return nil, err
}
return &Car{
Maker: maker,
Serial: serial, // 加工済みデータ
}, nil
}
③ 品質管理(バリデーション)
// 品質検査付き工場
func CreateValidCar(maker string, year int) (*Car, error) {
if year < 1900 {
return nil, errors.New("製造年が古すぎます")
}
if len(maker) == 0 {
return nil, errors.New("メーカー名必須")
}
return &Car{
Maker: maker,
Year: year,
}, nil
}
3. 優れた工場(ファクトリ)の設計ポイント
ポイント1:統一されたインターフェース
// 良い例:常に*Carとerrorを返す
func CreateCar(...) (*Car, error)
// 悪い例:場合によって返り値が異なる
func CreateCar(...) (*Car, error, string)
ポイント2:生産工程の隠蔽
// 内部実装は隠す(例:シリアル番号生成)
func generateSerial() string {
return fmt.Sprintf("CAR-%d", time.Now().UnixNano())
}
ポイント3:拡張可能な設計
// 車種ごとの工場
func CreateSedan() *Car { ... }
func CreateSUV() *Car { ... }
4. 実際の工場(ファクトリ)運用例
ケース1:DB接続工場
func CreateDBConnection(config Config) (*sql.DB, error) {
connStr := fmt.Sprintf(
"host=%s port=%d user=%s password=%s",
config.Host, config.Port, config.User, config.Pass,
)
db, err := sql.Open("postgres", connStr)
if err != nil {
return nil, fmt.Errorf("接続失敗: %w", err)
}
if err := db.Ping(); err != nil {
return nil, fmt.Errorf("接続確認失敗: %w", err)
}
return db, nil
}
ケース2:設定ファイル工場
func LoadConfig(path string) (*Config, error) {
raw, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("設定ファイル読み込み失敗: %w", err)
}
var config Config
if err := yaml.Unmarshal(raw, &config); err != nil {
return nil, fmt.Errorf("設定解析失敗: %w", err)
}
if err := config.Validate(); err != nil {
return nil, fmt.Errorf("設定検証失敗: %w", err)
}
return &config, nil
}
5. 工場長(開発者)へのアドバイス
-
単一責任原則
「1つの工場では1種類の製品だけを作る」 -
不良品対策
「必ずバリデーション工程を設ける」 -
生産ラインの最適化
「複雑な生成処理はサブ関数に分割」 -
工場の安全性
「非公開フィールドで内部状態を保護」 -
工場の拡張性
「インターフェースを活用して差し替え可能に」
🎯 究極の目標
「クライアントコードが『どう作られるか』を気にせず、
ただ『何が欲しいか』だけを伝えられる工場を作る」