介面卡是一種結構設計模式,它能讓具有不相容介面的物件進行協作。
這裡案例中:有一個call函式只接受介面 (trait)為Target的引數:
fn call(target: impl Target); |
如果有一個介面型別是SpecificTarget 作為需要作為引數傳入怎麼辦?
將這個SpecificTarget 轉換為Target。
就像將110伏插頭轉為220伏電壓插頭,這樣只能使用220伏的電器透過適配插頭就可以使用110伏電,這是去日本旅遊需要攜帶轉壓器的原因、
下面看看第一個介面trait:這是我們call函式可以接受的介面
pub trait Target { fn request(&self) -> String; } pub struct OrdinaryTarget; impl Target for OrdinaryTarget { fn request(&self) -> String { "Ordinary request.".into() } } |
但是,現在我們只有SpecificTarget這個介面,要傳給call函式:
pub struct SpecificTarget; impl SpecificTarget { pub fn specific_request(&self) -> String { ".tseuqer cificepS".into() } } |
那麼,就需要一個適配轉換器將SpecificTarget轉換為Target:
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() } } |
上面三個程式碼已經完成介面卡結構,下面是客戶端呼叫:
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); } |