面试题答案
一键面试设计思路
- 定义新旧接口:分别定义
Payment
接口和PaymentV2
接口,PaymentV2
继承Payment
接口以保持一定的兼容性。 - 实现类处理:让新的支付实现类实现
PaymentV2
接口,旧的实现类依然实现Payment
接口。 - 适配层:创建一个适配层,将实现了
Payment
接口的旧类适配成PaymentV2
接口,在适配层中对于新增的Refund
方法可以提供默认实现或者抛出不支持的异常。 - 逐步迁移:在业务逻辑中,可以逐步将使用旧接口的地方替换为新接口,在替换过程中通过适配层保证旧实现类依然可用。
关键代码片段
// 定义旧接口
type Payment interface {
Pay(amount float64) error
}
// 定义新接口,继承旧接口
type PaymentV2 interface {
Payment
Refund(amount float64) error
}
// 旧的支付实现类
type OldPayment struct{}
func (op *OldPayment) Pay(amount float64) error {
// 支付逻辑
return nil
}
// 适配层,将 OldPayment 适配为 PaymentV2
type OldPaymentAdapter struct {
OldPayment *OldPayment
}
func (opa *OldPaymentAdapter) Pay(amount float64) error {
return opa.OldPayment.Pay(amount)
}
func (opa *OldPaymentAdapter) Refund(amount float64) error {
// 可以提供默认实现,比如不支持退款
return errors.New("refund is not supported")
}
// 新的支付实现类
type NewPayment struct{}
func (np *NewPayment) Pay(amount float64) error {
// 支付逻辑
return nil
}
func (np *NewPayment) Refund(amount float64) error {
// 退款逻辑
return nil
}
在业务代码中,可以这样使用:
func main() {
var paymentV2 PaymentV2
oldPayment := &OldPayment{}
paymentV2 = &OldPaymentAdapter{OldPayment: oldPayment}
// 调用 Pay 方法
err := paymentV2.Pay(100)
if err != nil {
fmt.Println(err)
}
// 调用 Refund 方法
err = paymentV2.Refund(100)
if err != nil {
fmt.Println(err)
}
newPayment := &NewPayment{}
paymentV2 = newPayment
// 调用 Pay 方法
err = paymentV2.Pay(100)
if err != nil {
fmt.Println(err)
}
// 调用 Refund 方法
err = paymentV2.Refund(100)
if err != nil {
fmt.Println(err)
}
}