go design pattern
客户端不应该被迫依赖于它们不使用的方法。接口应该是小而完整的,而不是大而全的。
假设有一个云计算提供商整合服务,开始仅支持了阿里云,后来又支持了亚马逊云。
type CloudProvider interface {
storeFile(name string, date []byte) error
getFile(name string) error
getCDNAddress() string
}
type AlibabaCloud struct{}
func (a *AlibabaCloud) storeFile(name string, data []byte) error {
// Store file to Alibaba Cloud
fmt.Println("Store file to Alibaba Cloud: ", name)
return nil
}
func (a *AlibabaCloud) getFile(name string) error {
// Get file from Alibaba Cloud
fmt.Println("Get file from Alibaba Cloud: ", name, " data: ", string("data"))
return nil
}
func (a *AlibabaCloud) getCDNAddress() string {
// Get CDN address from Alibaba Cloud
return "https://cdn.alibaba.com"
}
type AmazonCloud struct{}
func (a *AmazonCloud) storeFile(name string, data []byte) error {
// Store file to Amazon Cloud
fmt.Println("Store file to Amazon Cloud: ", name, " data: ", string(data))
return nil
}
func (a *AmazonCloud) getFile(name string) error {
// Get file from Amazon Cloud
fmt.Println("Get file from Amazon Cloud: ", name)
return nil
}
func (a *AmazonCloud) getCDNAddress() string {
// No CDN address for Amazon Cloud
return ""
}
亚马逊云不支持CDN地址,但是我们的接口中定义了getCDNAddress
方法,这违反了接口隔离原则。
type CloudStorageProvider interface {
storeFile(name string, date []byte) error
getFile(name string) error
}
type CDNProvider interface {
getCDNAddress() string
}
type ModifyAlibabaCloud struct{}
func (m *ModifyAlibabaCloud) storeFile(name string, data []byte) error {
// Store file to Alibaba Cloud
fmt.Println("Store file to Alibaba Cloud: ", name, " data: ", string(data))
return nil
}
func (m *ModifyAlibabaCloud) getFile(name string) error {
// Get file from Alibaba Cloud
fmt.Println("Get file from Alibaba Cloud: ", name)
return nil
}
func (m *ModifyAlibabaCloud) getCDNAddress() string {
// Get CDN address from Alibaba Cloud
return "https://cdn.alibaba.com"
}
type ModifyAmazonCloud struct{}
func (m *ModifyAmazonCloud) storeFile(name string, data []byte) error {
// Store file to Amazon Cloud
fmt.Println("Store file to Amazon Cloud: ", name, " data: ", string(data))
return nil
}
func (m *ModifyAmazonCloud) getFile(name string) error {
// Get file from Amazon Cloud
fmt.Println("Get file from Amazon Cloud: ", name)
return nil
}
我们将接口拆分为两个接口,CloudStorageProvider
和CDNProvider
,这样亚马逊云就不需要实现getCDNAddress
方法了。
创建的接口越多,代码就会变得越复杂,所以我们需要根据实际情况来决定是否拆分接口。