上一篇《建造者模式》 下一篇《桥接模式》
适配器模式,它是一种结构型设计模式,它用于将一个类的接口转换成客户端所期待的另一种接口,使得原本因接口不兼容而无法一起工作的两个类能够协同工作。
适配器模式包括类适配器模式和对象适配器模式。类适配器模式依赖于继承关系实现,因此其耦合度较高。对象适配器模式则依赖于组合或聚合关系实现,因此其耦合度较低。
适配器模式的结构包括抽象原有接口、具体原有接口、抽象目标接口和适配器。适配器实现抽象目标接口,并实现目标接口的行为。
适配器模式包含以下三个角色:
1、源(Adaptee):需要被适配的对象或类型,相当于插头。
2、适配器(Adapter):连接目标和源的中间对象,相当于插头转换器。
3、目标(Target):期待得到的目标,相当于插座。
适配器模式的使用场景:
1、系统需要使用现有的类,但现有类的接口不符合系统的需要。
2、需要一个统一的输出接口,而输入类型不可预知。例如,在Android开发中的Adapter模式,用户的数据各式各样,但最终都是通过getView()返回一个View,这是适配器模式的一个很好的应用场景。
3、创建一个可以复用的类。例如,Android中的Adapter模式可以使得该类可以与其他不相关的类或不可预见的类协同工作。
适配器模式是一种结构型设计模式,它用于将一个类的接口转换成客户端所期待的另一种接口,使得原本因接口不兼容而无法一起工作的两个类能够协同工作。
适配器模式的创建步骤:
1、创建Target接口。这个接口定义了目标类需要实现的方法。
2、创建源类(Adaptee)。这个类中可能包含了一些需要适配的方法。
3、创建适配器类(Adapter)。该类继承自源类并实现目标接口。适配器类需要实现目标接口中定义的方法,并将源类的原有方法封装成符合目标接口要求的方法。
在适配器类中,我们需要将Target接口的方法和Adaptee类的方法进行适配。具体来说,我们需要将Target接口的方法调用转发到Adaptee类的方法上。
适配器模式的优点,主要包括:
1、更好的复用性:适配器模式允许系统使用已经存在的类,即使其接口不符合系统的需求,通过适配器模式可以解决不兼容的问题,使这些功能类得到复用。
2、增加类的透明性和复用性:适配器模式将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
3、灵活性和扩展性:适配器模式通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
适配器模式的缺点,主要包括:
1、增加系统的复杂性:适配器模式需要引入一个额外的适配器类,增加了系统的复杂性。
不适合大型系统:适配器模式会导致系统的结构变得复杂,并可能影响到系统的性能,因此不适合大型系统。
2、破坏封装性:适配器模式需要访问适配者的私有方法和属性,这会破坏适配者的封装性。
3、降低了代码的可读性和可维护性:由于适配器模式的使用需要额外的类和方法,这会使得代码更加复杂和难以理解,降低了代码的可读性和可维护性。
以下是一个示例,展示了如何在C#中实现适配器模式:
using System;
// 目标接口
public interface Target
{
void Request();
}
// 源类
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee's specific request.");
}
}
// 适配器类
public class Adapter : Target
{
private Adaptee adaptee;
public Adapter(Adaptee adaptee)
{
this.adaptee = adaptee;
}
public void Request()
{
adaptee.SpecificRequest();
}
}
// 客户端类
public class Client
{
public static void Main()
{
Adaptee adaptee = new Adaptee(); // 创建源类对象
Target target = new Adapter(adaptee); // 创建适配器,并将源类对象传入适配器构造函数中进行适配
target.Request(); // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
}
适配器模式通常通过以下方式实现:
// 目标接口
interface Target {
void request();
}
// 源类
class Adaptee {
public void specificRequest() {
System.out.println("Adaptee's specific request.");
}
}
// 适配器类
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
// 客户端类
class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee(); // 创建源类对象
Target target = new Adapter(adaptee); // 创建适配器,并将源类对象传入适配器构造函数中进行适配
target.request(); // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
}
在JavaScript中,适配器实现方式如下:
// 目标接口
interface Target {
request();
}
// 源类
class Adaptee {
specificRequest() {
console.log('Adaptee\'s specific request.');
}
}
// 适配器类
class Adapter implements Target {
constructor(adaptee: Adaptee) {
this.adaptee = adaptee;
}
request() {
this.adaptee.specificRequest();
}
}
// 客户端类
class Client {
static main() {
const adaptee = new Adaptee(); // 创建源类对象
const target = new Adapter(adaptee); // 创建适配器,并将源类对象传入适配器构造函数中进行适配
target.request(); // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
}
以下是在C++中实现适配器模式:
// 目标接口
class Target {
public:
virtual void request() = 0;
};
// 源类
class Adaptee {
public:
void specificRequest() {
cout << "Adaptee's specific request." << endl;
}
};
// 适配器类
class Adapter : public Adaptee, public Target {
public:
void request() override {
specificRequest();
}
};
// 客户端类
class Client {
public:
static void main() {
Adaptee* adaptee = new Adaptee(); // 创建源类对象
Target* target = new Adapter(adaptee); // 创建适配器,并将源类对象传入适配器构造函数中进行适配
target->request(); // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
};
下面是一个简单的Python适配器模式示例:
# 目标接口
class Target:
def request(self):
pass
# 源类
class Adaptee:
def specific_request(self):
print("Adaptee's specific request.")
# 适配器类
class Adapter(Adaptee, Target):
def request(self):
self.specific_request()
# 客户端类
class Client:
def main(self):
adaptee = Adaptee() # 创建源类对象
target = Adapter(adaptee) # 创建适配器,并将源类对象传入适配器构造函数中进行适配
target.request() # 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
client = Client()
client.main()
以下是一个示例,展示了如何在go中实现适配器模式:
package main
import "fmt"
// 目标接口
type Target interface {
Request()
}
// 源类
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() {
fmt.Println("Adaptee's specific request.")
}
// 适配器类
type Adapter struct {
adaptee *Adaptee
}
func (a *Adapter) Request() {
a.adaptee.SpecificRequest()
}
// 客户端类
type Client struct{}
func (c *Client) Main() {
adaptee := &Adaptee{} // 创建源类对象
target := &Adapter{adaptee: adaptee} // 创建适配器,并将源类对象传入适配器构造函数中进行适配
target.Request() // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
func main() {
client := &Client{} // 创建客户端对象
client.Main() // 执行客户端的主要逻辑,完成适配器的使用示例
}
以下是一个示例,展示了如何在PHP中实现适配器模式:
interface Target {
public function request();
}
class Adaptee {
public function specificRequest() {
echo "Adaptee's specific request.";
}
}
class Adapter implements Target {
private $adaptee;
public function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
public function request() {
$this->adaptee->specificRequest();
}
}
class Client {
public function main() {
$adaptee = new Adaptee(); // 创建源类对象
$target = new Adapter($adaptee); // 创建适配器,并将源类对象传入适配器构造函数中进行适配
$target->request(); // 客户端调用目标接口中的方法,实际上会调用适配器中的方法,适配器中会调用源类的方法
}
}
$client = new Client();
$client->main();
在上面的示例中,目标接口是Target,它定义了客户端所期待的接口。源类是Adaptee,它拥有原本的接口,但不符合目标接口。适配器类是Adapter,它实现目标接口并封装源类的原有方法。客户端类是Client,它通过调用目标接口中定义的方法来调用适配器类的方法。适配器的内部会自动调用源类的方法,实现了源类和目标接口的适配。
《完结》
上一篇《建造者模式》 下一篇《桥接模式》