Rust語言之GoF設計模式:介面卡Adapter

banq發表於2022-09-25

介面卡是一種結構設計模式,它能讓具有不相容介面的物件進行協作。

這裡案例中:有一個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);
}


 

相關文章