桥Bridge模式是将业务逻辑或巨大的类型划分为独立的类型层次,可以独立开发。
案例,遥控器能遥控电视或收音机等设备,将遥控器与被遥控操作的设备分离,由于有共同的接口,相同的遥控器可以与不同的设备一起工作,估计是通过红外,这样的遥控器称为万能遥控器。
桥接模式能在改变甚至创建新的类情况下,不触及相对层次的代码。
先看看设备代码:
mod radio; mod tv;
pub use radio::Radio; pub use tv::Tv;
pub trait Device { fn is_enabled(&self) -> bool; fn enable(&mut self); fn disable(&mut self); fn volume(&self) -> u8; fn set_volume(&mut self, percent: u8); fn channel(&self) -> u16; fn set_channel(&mut self, channel: u16); fn print_status(&self); }
|
这个设备能调节音量,改变频道
设备具体实现电视机:
tv.rs:
use super::Device;
#[derive(Clone)] pub struct Tv { on: bool, volume: u8, channel: u16, }
impl Default for Tv { fn default() -> Self { Self { on: false, volume: 30, channel: 1, } } }
impl Device for Tv { fn is_enabled(&self) -> bool { self.on }
fn enable(&mut self) { self.on = true; }
fn disable(&mut self) { self.on = false; }
fn volume(&self) -> u8 { self.volume }
fn set_volume(&mut self, percent: u8) { self.volume = std::cmp::min(percent, 100); }
fn channel(&self) -> u16 { self.channel }
fn set_channel(&mut self, channel: u16) { self.channel = channel; }
fn print_status(&self) { println!("------------------------------------"); println!("| I'm TV set."); println!("| I'm {}", if self.on { "enabled" } else { "disabled" }); println!("| Current volume is {}%", self.volume); println!("| Current channel is {}", self.channel); println!("------------------------------------\n"); } }
|
收音机代码:radio.rs
下面是看看遥控器代码:
mod.rs
mod advanced; mod basic;
pub use advanced::AdvancedRemote; pub use basic::BasicRemote;
use crate::device::Device;
pub trait HasMutableDevice<D: Device> { fn device(&mut self) -> &mut D; }
pub trait Remote<D: Device>: HasMutableDevice<D> { fn power(&mut self) { println!("Remote: power toggle"); if self.device().is_enabled() { self.device().disable(); } else { self.device().enable(); } }
fn volume_down(&mut self) { println!("Remote: volume down"); let volume = self.device().volume(); self.device().set_volume(volume - 10); }
fn volume_up(&mut self) { println!("Remote: volume up"); let volume = self.device().volume(); self.device().set_volume(volume + 10); }
fn channel_down(&mut self) { println!("Remote: channel down"); let channel = self.device().channel(); self.device().set_channel(channel - 1); }
fn channel_up(&mut self) { println!("Remote: channel up"); let channel = self.device().channel(); self.device().set_channel(channel + 1); } }
|
这个遥控器只对设备Device抽象接口操作:设置音量和更好频道。下面是一个遥控器的一个基础实现:
basic.rs
use crate::device::Device;
use super::{HasMutableDevice, Remote};
pub struct BasicRemote<D: Device> { device: D, }
impl<D: Device> BasicRemote<D> { pub fn new(device: D) -> Self { Self { device } } }
impl<D: Device> HasMutableDevice<D> for BasicRemote<D> { fn device(&mut self) -> &mut D { &mut self.device } }
impl<D: Device> Remote<D> for BasicRemote<D> {}
|
一个基本的遥控器可能只有两个按钮,但您可以使用额外的高级功能来扩展它,例如额外的电池或触摸屏。
还有一个高级遥控器实现:advanced.rs
以上准备好了桥模式的分散组件,下面看看如何在客户端将这些组件组合搭桥:
main.rs:
mod device; mod remotes;
use device::{Device, Radio, Tv}; use remotes::{AdvancedRemove, BasicRemote, HasMutableDevice, Remote};
fn main() { test_device(Tv::default()); test_device(Radio::default()); }
fn test_device(device: impl Device + Clone) { println!("Tests with basic remote."); let mut basic_remote = BasicRemote::new(device.clone()); basic_remote.power(); basic_remote.device().print_status();
println!("Tests with advanced remote."); let mut advanced_remote = AdvancedRemove::new(device); advanced_remote.power(); advanced_remote.mute(); advanced_remote.device().print_status(); }
|
上述代码运行输出:
Tests with basic remote. Remote: power toggle ------------------------------------ | I'm TV set. | I'm enabled | Current volume is 30% | Current channel is 1 ------------------------------------
Tests with advanced remote. Remote: power toggle Remote: mute ------------------------------------ | I'm TV set. | I'm enabled | Current volume is 0% | Current channel is 1 ------------------------------------
Tests with basic remote. Remote: power toggle ------------------------------------ | I'm radio. | I'm enabled | Current volume is 30% | Current channel is 1 ------------------------------------
Tests with advanced remote. Remote: power toggle Remote: mute ------------------------------------ | I'm radio. | I'm enabled | Current volume is 0% | Current channel is 1 ------------------------------------
|
当我们需要添加新的设备,如小米音响时,能不能通过这个万能遥控器实现遥控呢?首先需要打开万能遥控器App,找到相应的小米品牌下的音响,添加以后就可以了,上述代码也是实现现实生活中这种使用过程的思路。
桥模式一种用组合替代继承的做法,这里关键抽象是”遥控器“,这是一个耦合了设备Device的万能遥控器,按照继承思路,遥控器和设备Device应该各自有自己的接口类型,不应该混合在一起,因为它们是不同类型分类,不同的东西,但是这里遥控器将设备Device引入进来,是包含或组合了Device,相当于搭了一座桥。这样有新的设备Device类型也是通过这个桥接、组合思路实现音量和频道的调节。
桥模式 = 组合 + 面向接口编程