Вступление
Шаблон фасада используется как способ скрыть более сложную логику. Фасад может выполнять следующее:
- Улучшить удобство использования библиотеки или API за счет маскировки взаимодействия с более сложными компонентами базового кода.
- Предоставить интерфейсы, зависящие от контекста. Это означает, что каждый клиент API может получить свой собственный фасад, в зависимости от вариантов использования.
Шаблон фасада обычно используется в следующих случаях:
- Подсистема или несколько подсистем имеют тесно связанные элементы.
- В многоуровневом программном обеспечении вам может понадобиться точка входа для каждого уровня.
- В случае очень сложных систем фасад может помочь
На что это похоже? Что ж, это довольно просто:
Класс Facade
имеет простой интерфейс, скрывающий тот факт, что он может иметь более сложное взаимодействие, например, с ClassA
и ClassB
. Этот пример простой, но вы можете себе представить, что в сложных системах существуют десятки или сотни классов, с которыми должен взаимодействовать фасад.
Реализация в Rust
В пустом каталоге откройте свой терминал или командную строку и введите:
cargo new rust_facade
cd rust_facade
Теперь откройте этот каталог в вашей любимой IDE и откройте main.rs файл в вашем каталоге src/.
Мы начнем с определения точечной структуры:
struct Point {
x: f32,
y: f32,
}
impl Point {
fn new(x: f32, y: f32) -> Point {
Point { x: x, y: y }
}
}
Точка просто получает две координаты, X
и Y
. Я также добавил простой конструктор.
Структура ShapeMaker
поможет нам построить квадрат:
struct ShapeMaker<'s> {
p: &'s Point,
}
impl<'s> ShapeMaker<'s> {
fn new(p: &'s Point) -> ShapeMaker<'s> {
ShapeMaker { p: p }
}
fn create_square(&self,size: f32) -> Point {
Point::new(self.p.x+size,self.p.y+size)
}
}
Структура ShapeMaker
просто получает отправную точку. Он вычисляет вторую точку квадрата в методе create_square()
, добавляя параметр size
как к координатам X
, так и Y
точки.
Структура ShapeMeasurer
измеряет расстояние между двумя точками, используя теорему Пифогора:
struct ShapeMeasurer<'s> {
first: &'s Point,
second: &'s Point,
}
impl<'s> ShapeMeasurer<'s> {
fn new(first: &'s Point, second: &'s Point) -> ShapeMeasurer<'s> {
ShapeMeasurer { first: first, second: second }
}
fn get_distance(&self) -> f32 {
let x = self.first.x - self.second.x;
let y = self.first.y - self.second.y;
(x*x + y*y).sqrt()
}
}
Наконец, у нас есть измеритель площади, который, исходя из начальной точки и заданного размера, может измерить диагональ квадрата:
struct SquareMeasurer<'s> {
starting_point: &'s Point,
}
impl<'s> SquareMeasurer<'s> {
fn new(starting_point: &'s Point) -> SquareMeasurer<'s> {
SquareMeasurer { starting_point: starting_point }
}
fn measure_square_diagonal(&self, size: f32) -> f32 {
let p = ShapeMaker::new(self.starting_point).create_square(size);
ShapeMeasurer::new(self.starting_point, &p).get_distance()
}
}
Теперь мы можем это проверить:
fn main() {
let p = Point::new(3.0, 4.0);
let sm = SquareMeasurer::new(&p);
println!("Diagonal of a square with size 3 is {}", sm.measure_square_diagonal(3.0));
}
Строка за строкой:
- Мы создаем новую точку и передаем ее в
SquareMeasurer
. - Вызывая метод
measure_square_diagonal()
,SquareMeasurer
вызывает базовые классы, чтобы найти размер диагонали. - Мы выводим результат. В нашем тестовом примере это должно быть около 4.2.
Вывод
Это не самый сложный шаблон для реализации. Как и в случае с большинством шаблонов проектирования, это просто выглядит как здравый смысл, скрывающий сложность. В следующей статье я надеюсь предоставить вам более сложный пример для этого шаблона.