设计模式解密:适配器模式的终极指南(PHP/Go双实现)
一、什么是适配器模式?
适配器模式(Adapter Pattern) 是一种结构型设计模式,用于将一个类的接口转换成客户端期望的另一个接口。适配器模式的核心思想是通过一个中间层(适配器)来解决接口不兼容的问题,使原本不兼容的类能够协同工作。
核心角色:
目标接口(Target):客户端期望的接口
适配者(Adaptee):需要被适配的类
适配器(Adapter):实现目标接口并包装适配者
二、适用场景
✅ 需要使用现有类,但其接口与客户端不兼容
✅ 需要复用一些现有的类,但这些类不符合系统接口规范
✅ 需要统一多个类的接口
✅ 需要解耦客户端与具体实现
三、PHP实现方案
1. 类适配器(继承方式)
interface Target {
public function request(): string;
}
class Adaptee {
public function specificRequest(): string {
return "Specific request";
}
}
class Adapter extends Adaptee implements Target {
public function request(): string {
return $this->specificRequest();
}
}
// 使用示例
$adapter = new Adapter();
echo $adapter->request(); // 输出:Specific request
2. 对象适配器(组合方式)
interface Target {
public function request(): string;
}
class Adaptee {
public function specificRequest(): string {
return "Specific request";
}
}
class Adapter implements Target {
private $adaptee;
public function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
public function request(): string {
return $this->adaptee->specificRequest();
}
}
// 使用示例
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
echo $adapter->request(); // 输出:Specific request
四、Go实现方案
1. 接口适配器
package main
import "fmt"
type Target interface {
Request() string
}
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() string {
return "Specific request"
}
type Adapter struct {
adaptee *Adaptee
}
func NewAdapter(adaptee *Adaptee) *Adapter {
return &Adapter{adaptee: adaptee}
}
func (a *Adapter) Request() string {
return a.adaptee.SpecificRequest()
}
// 使用示例
func main() {
adaptee := &Adaptee{}
adapter := NewAdapter(adaptee)
fmt.Println(adapter.Request()) // 输出:Specific request
}
2. 函数适配器
package main
import "fmt"
type TargetFunc func() string
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() string {
return "Specific request"
}
func Adapt(adaptee *Adaptee) TargetFunc {
return func() string {
return adaptee.SpecificRequest()
}
}
// 使用示例
func main() {
adaptee := &Adaptee{}
adapter := Adapt(adaptee)
fmt.Println(adapter()) // 输出:Specific request
}
五、关键实现差异对比
六、模式优缺点分析
👍 优点:
解耦客户端与适配者:客户端无需修改即可使用适配者
复用现有类:无需修改现有代码即可复用
灵活性高:支持多种适配方式(类适配器、对象适配器)
👎 缺点:
增加复杂度:引入额外的类和接口
过度设计:简单场景下可能显得冗余
七、实际应用案例
1. 第三方库集成
// PHP示例
$thirdPartyService = new ThirdPartyService();
$adapter = new ThirdPartyServiceAdapter($thirdPartyService);
$client = new Client($adapter);
$client->execute();
2. 日志系统适配
// Go示例
type Logger interface {
Log(message string)
}
type FileLogger struct{}
func (f *FileLogger) LogToFile(message string) {
fmt.Println("Log to file:", message)
}
type FileLoggerAdapter struct {
fileLogger *FileLogger
}
func NewFileLoggerAdapter(fileLogger *FileLogger) *FileLoggerAdapter {
return &FileLoggerAdapter{fileLogger: fileLogger}
}
func (f *FileLoggerAdapter) Log(message string) {
f.fileLogger.LogToFile(message)
}
// 使用示例
func main() {
fileLogger := &FileLogger{}
adapter := NewFileLoggerAdapter(fileLogger)
adapter.Log("Hello, World!") // 输出:Log to file: Hello, World!
}
3. 数据格式转换
// PHP示例
$jsonData = '{"name": "John", "age": 30}';
$adapter = new JsonToXmlAdapter($jsonData);
$xmlData = $adapter->convert();
echo $xmlData;
八、与装饰器模式的区别
九、总结
适配器模式是解决接口不兼容问题的经典设计模式。通过引入适配器,我们可以复用现有代码,同时保持系统的灵活性和可维护性。无论是PHP的类适配器还是Go的函数适配器,适配器模式都能显著提升代码的复用性和扩展性。
在下一篇文章中,我们将探讨 桥接模式 及其在抽象与实现分离中的应用。敬请期待!
下一篇预告:设计模式系列(七)——桥接模式:抽象与实现的桥梁
License:
CC BY 4.0