Rust语言之GoF设计模式:适配器Adapter

22-09-25 banq

适配器是一种结构设计模式,它能让具有不兼容接口的对象进行协作。

这里案例中:有一个call函数只接受接口 (trait)为Target的参数:

fn call(target: impl Target);

如果有一个接口类型是SpecificTarget 作为需要作为参数传入怎么办?
将这个SpecificTarget 转换为Target。
就像将110伏插头转为220伏电压插头,这样只能使用220伏的电器通过适配插头就可以使用110伏电,这是去日本旅游需要携带转压器的原因、

下面看看第一个接口trait:这是我们call函数可以接受的接口

target.rs

pub trait Target {
    fn request(&self) -> String;
}

pub struct OrdinaryTarget;

impl Target for OrdinaryTarget {
    fn request(&self) -> String {
        "Ordinary request.".into()
    }
}


但是,现在我们只有SpecificTarget这个接口,要传给call函数:

adaptee.rs:

pub struct SpecificTarget;

impl SpecificTarget {
    pub fn specific_request(&self) -> String {
        ".tseuqer cificepS".into()
    }
}


那么,就需要一个适配转换器将SpecificTarget转换为Target:

adapter.rs

use crate::{adaptee::SpecificTarget, Target};

///将adaptee的'SpecificTarget'转换为兼容的`Target`输出
pub struct TargetAdapter {
    adaptee: SpecificTarget,
}

impl TargetAdapter {
    pub fn new(adaptee: SpecificTarget) -> Self {
        Self { adaptee }
    }
}

impl Target for TargetAdapter {
    fn request(&self) -> String {
       // 这里是将原来的specific输出 "改编 "为兼容Target的输出。
        self.adaptee.specific_request().chars().rev().collect()
    }
}


上面三个代码已经完成适配器结构,下面是客户端调用:

main.rs

mod adaptee;
mod adapter;
mod target;

use adaptee::SpecificTarget;
use adapter::TargetAdapter;
use target::{OrdinaryTarget, Target};

/// 只能调用 "Target "接口的call函数
///
/// 为了更好地理解适配器模式,想象一下这是
/// 一个客户端代码,它只能在一个特定的接口上操作
/// (`Target` trait only)。这意味着一个不兼容的接口不能被
/// 在没有适配器的情况下传递到这里。
fn call(target: impl Target) {
    println!("'{}'", target.request());
}

fn main() {
    let target = OrdinaryTarget;

    print!("兼容于target的任何参数都能直接被调用: ");
    call(target);

    let adaptee = SpecificTarget;

    println!(
        "Adaptee 与客户端不兼容: '{}'",
        adaptee.specific_request()
    );

    let adapter = TargetAdapter::new(adaptee);

    print!("但是使用 adapter 以后,客户端可以调用call函数了: ");
    call(adapter);
}