首页 后端开发 php教程 面向对象进阶-设计模式:适配器模式

面向对象进阶-设计模式:适配器模式

May 20, 2017 pm 02:35 PM
设计模式 适配器模式 面向对象

什么是适配器模式?

适配器模式只是将某个对象的接口适配为另一个对象所期望的接口。

适配器模式应用问题与解决方案

在应用程序中,您也许会使用一个在体系结构上可靠稳定的工作代码库。不过我们常常会添加新的功能,这些功能要求采用不同的方式使用现有的对象,而不是采用原先设计的方式。此时,障碍可能只是新功能需要一个不同的名字。在较为复杂的场景中,障碍也可能是新功能需要与原始对象稍有不同的行为。

针对上述问题,我们采用的解决方案是使用适配器模式构建另一个对象。这个Adapter对象充当了原始应用与新功能之间的中介。适配器模式为已有的对象定义了新的接口,从而能够匹配新对象的要求。

问题

假设支付宝支付类的功能如下:

/** 
 * 支付宝支付类 
 */  
class Alipay  
{  
    public function sendPayment()  
    {  
        echo '使用支付宝支付。';  
    }  
}  
  
// 客户端代码  
$alipay = new Alipay();  
$alipay->sendPayment();
登录后复制

我们直接实例化Alipay类完成支付功能,这样的客户端代码可能很多。

一段时间后,如果支付宝的Alipay类升级,方法名由sendPayment()变成goPayment()会怎样?

所有用了sendPayment()的客户端代码都要改变。

如果Alipay类频繁升级,或者客户端在很多地方使用,这会是极大的工作量。

解决

现在我们用适配器模式来解决。

我们在客户端和Alipay类之间加一个中间类,也就是适配器类,转换原始的Alipay为客户端需要的形式。

为让客户端能调用到统一的类方法,我们先定义一个适配器接口:

/** 
 * 适配器接口,所有的支付适配器都需实现这个接口。 
 * 不管第三方支付实现方式如何,对于客户端来说,都 
 * 用pay()方法完成支付 
 */  
interface PayAdapter  
{  
    public function pay();  
}
登录后复制

因为Alipay类我们无法控制,而且它有可能经常更新,所以我们不对它做任何修改。

我们新建一个AlipayAdapter适配器类,在pay()中转换Alipay的支付功能,如下:

/** 
 * 支付宝适配器 
 */  
class AlipayAdapter implements PayAdapter  
{  
    public function pay()  
    {  
        // 实例化Alipay类,并用Alipay的方法实现支付  
        $alipay = new Alipay();  
        $alipay->sendPayment();  
    }  
}
登录后复制

客户端使用方式:

// 客户端代码  
$alipay = new AlipayAdapter();  
// 用pay()方法实现支付  
$alipay->pay();
登录后复制

这样,当Alipay的支付方法改变,只需要修改AlipayAdapter类就可以了。

适配新类

有了适配器后,扩展也变得更容易了。

继续以上的例子,在支付宝的基础上,我们再增加微信支付,它与支付宝的支付方式不同,必须通过扫码才能支付。

这种情况也应该使用适配器,而不是直接使用微信的支付功能。

代码如下:

/** 
 * 微信支付类 
 */  
class WechatPay  
{  
    public function scan()  
    {  
        echo '扫描二维码后,';  
    }  
  
    public function doPay()  
    {  
        echo '使用微信支付';  
    }  
}  
  
/** 
 * 微信支付适配器 
 */  
class WechatPayAdapter implements PayAdapter  
{  
    public function pay()  
    {  
        // 实例化WechatPay类,并用WechatPay的方法实现支付。  
        // 注意,微信支付的方式和支付宝的支付方式不一样,但是  
        // 适配之后,他们都能用pay()来实现支付功能。  
        $wechatPay = new WechatPay();  
        $wechatPay->scan();  
        $wechatPay->doPay();  
    }  
}
登录后复制

客户端使用:

// 客户端代码  
$wechat = new WechatPayAdapter();  
// 也是用pay()方法实现支付  
$wechat->pay();
登录后复制

这就是适配器的扩展特性。

我们创建了一个用于处理第三方类(支付宝、微信支付)的方法,

如果它们的API有变化,我们仅需修改客户端依赖的适配器类就可以,不用修改、暴露第三方类本身。

UML图

以上适配器模式的代码对应UML如下:

1.png

总结

大的应用都会不断地加入新库和新API。

为避免它们的变更引发问题,应该用适配器模式包装起来,提供应用统一的引用方式。

它会让我们的代码更具结构化,便于管理和扩展。

以上是面向对象进阶-设计模式:适配器模式的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP高级特性:面向对象编程的最佳实践 PHP高级特性:面向对象编程的最佳实践 Jun 05, 2024 pm 09:39 PM

PHP中OOP最佳实践包括命名约定、接口与抽象类、继承与多态、依赖注入。实战案例包括:使用仓库模式管理数据,使用策略模式实现排序。

Java框架中设计模式与架构模式的区别 Java框架中设计模式与架构模式的区别 Jun 02, 2024 pm 12:59 PM

在Java框架中,设计模式和架构模式的区别在于:设计模式定义了在软件设计中解决常见问题的抽象解决方案,关注类和对象之间的交互,如工厂模式。架构模式定义了系统结构和模块之间的关系,关注系统组件的组织和交互,如分层架构。

PHP面向对象编程的深入理解:面向对象编程的调试技巧 PHP面向对象编程的深入理解:面向对象编程的调试技巧 Jun 05, 2024 pm 08:50 PM

通过掌握追踪对象状态、设置断点、追踪异常和利用xdebug扩展,可以有效调试PHP面向对象编程代码。1.追踪对象状态:使用var_dump()和print_r()查看对象属性和方法值。2.设置断点:在开发环境中设置断点,调试器将在执行到达断点时暂停,便于检查对象状态。3.追踪异常:使用try-catch块和getTraceAsString()获取异常发生时的堆栈跟踪和消息。4.利用调试器:xdebug_var_dump()函数可在代码执行过程中检查变量的内容。

Java设计模式之装饰器模式剖析 Java设计模式之装饰器模式剖析 May 09, 2024 pm 03:12 PM

装饰器模式是一种结构型设计模式,允许动态添加对象功能,无需修改原始类。它通过抽象组件、具体组件、抽象装饰器和具体装饰器的协作实现,可以灵活扩展类功能,满足变化的需求。示例中,将牛奶和摩卡装饰器添加到Espresso,总价为2.29美元,展示了装饰器模式在动态修改对象行为方面的强大功能。

Java设计模式之适配器模式的妙用 Java设计模式之适配器模式的妙用 May 09, 2024 pm 12:54 PM

适配器模式是一种结构型设计模式,允许不兼容对象协同工作,它将一个接口转换为另一个,使对象能够顺利交互。对象适配器通过创建包含被适配对象的适配器对象,并实现目标接口,实现适配器模式。在一个实战案例中,通过适配器模式,客户端(如MediaPlayer)可以播放高级格式的媒体(如VLC),尽管其本身仅支持普通媒体格式(如MP3)。

PHP设计模式:测试驱动开发实践 PHP设计模式:测试驱动开发实践 Jun 03, 2024 pm 02:14 PM

TDD用于编写高质量PHP代码,步骤包括:编写测试用例,描述预期功能并使其失败。编写代码,仅使测试用例通过,无需过分优化或详细设计。测试用例通过后,优化和重构代码以提高可读性、可维护性和可扩展性。

Guice框架中设计模式的应用 Guice框架中设计模式的应用 Jun 02, 2024 pm 10:49 PM

Guice框架应用了多项设计模式,包括:单例模式:通过@Singleton注解确保类只有一个实例。工厂方法模式:通过@Provides注解创建工厂方法,在依赖注入时获取对象实例。策略模式:将算法封装成不同策略类,通过@Named注解指定具体策略。

java框架中使用设计模式的优缺点有哪些? java框架中使用设计模式的优缺点有哪些? Jun 01, 2024 pm 02:13 PM

Java框架中使用设计模式的优点包括:代码可读性、可维护性和可扩展性增强。缺点包括:过度使用导致复杂性、性能开销以及学习曲线陡峭。实战案例:代理模式用于延迟加载对象。明智地使用设计模式可充分利用其优势并最小化缺点。

See all articles