

goでストラテジーパターンを用いてある処理のふるまいを変更していました。  
すべての具体的なストラテジーに対して、付加的な処理を入れる場合と入れない場合が出てきたので、デコレーターパターンを用いて対応を検討しました。chatgptに質問すると、下記のように、インターフェースを埋め込むことで対応できることがわかりました。この場合、デコレーター構造体側でストラテジーの大元のインターフェースのメソッドをすべて実装しないとデコレーターがストラテジーインターフェースを満たしてくれませんでした。ほとんど委譲しかしないメソッドを定義しないとならないのですが(下記の例で言うと、Refundのようなメソッドが大量にあるイメージです。)、これは仕方のないことでしょうか。

ほかにgoらしいスマートなやり方があれば教えていただきたいです。よろしくお願いいたします。

[code]

    package main
    
    import "fmt"
    
    // 支払い方法のストラテジー
    type PaymentStrategy interface {
        Pay(amount float64) string
        Refund(amount float64) string
    }
    
    // クレジットカード支払い
    type CreditCardStrategy struct{}
    
    func (c *CreditCardStrategy) Pay(amount float64) string {
        return fmt.Sprintf("クレジットカードで %.2f 円支払いました", amount)
    }
    
    func (c *CreditCardStrategy) Refund(amount float64) string {
        return fmt.Sprintf("クレジットカードで %.2f 円返金しました", amount)
    }
    
    // 手数料デコレーター
    type FeeDecorator struct {
        strategy PaymentStrategy
        fee      float64
    }
    
    func (d *FeeDecorator) Pay(amount float64) string {
        totalAmount := amount + d.fee
        return fmt.Sprintf("%s（手数料 %.2f 円込み）", d.strategy.Pay(totalAmount), d.fee)
    }
    
    func (d *FeeDecorator) Refund(amount float64) string {
        // 手数料デコレーターはRefundメソッドに手数料を加える必要はないため、そのまま委譲する
        return d.strategy.Refund(amount)
    }
    
    func main() {
        creditCard := &CreditCardStrategy{}
        creditCardWithFee := &FeeDecorator{strategy: creditCard, fee: 2.0}
    
        fmt.Println(creditCardWithFee.Pay(100.0))
        fmt.Println(creditCardWithFee.Refund(50.0))
    }
    
    
    
[/code]


CC BY-SA 4.0
2023-08-27T11:55:46.327
96056
2023-09-06T04:58:56.043
59594
question
go
goでのデコレーターとストラテジーの実装について


埋め込みはこう書くのでは？

[code]

    // 手数料デコレーター
    type FeeDecorator struct {
        PaymentStrategy
        fee float64
    }
    
    func (d *FeeDecorator) Pay(amount float64) string {
        totalAmount := amount + d.fee
        return fmt.Sprintf("%s（手数料 %.2f 円込み）", d.PaymentStrategy.Pay(totalAmount), d.fee)
    }
    
    func main() {
        creditCard := &CreditCardStrategy{}
        creditCardWithFee := &FeeDecorator{PaymentStrategy: creditCard, fee: 2.0}
    
        fmt.Println(creditCardWithFee.Pay(100.0))
        fmt.Println(creditCardWithFee.Refund(50.0))
    }
    
[/code]

<https://go.dev/play/p/ZrtdKT3q4IP>


CC BY-SA 4.0
2023-09-06T04:58:56.043
96140
2023-09-06T04:58:56.043
7837
96056
answer