паттерн State
От: sergii.p  
Дата: 27.02.23 10:14
Оценка: 6 (1) -1
увидел довольно оригинальную технику реализации паттерна State на расте. На других языках такое городить тоже можно, но результат может не воодушевить.
Допустим реализуем сетевое соединение. Оно может быть либо в закрытом состоянии, либо открытом. Нам желательно в compile time запретить вызов метода close или write для ещё не открытого соединения (в классической реализации бросали исключения).
Приступим к реализации.
Сначала делаем пустые структуры для маркера состояния:
struct Open;
struct Close;

Затем реализуем собственно класс соединения:
struct Connection<State = Close> {
    ...
    state: std::marker::PhantomData<State>, // иначе получим ошибку error[E0392]: parameter `State` is never used
}

Реализуем наши методы для закрытого соединения:
impl Connection<Close> {
    fn open(self) -> Connection<Open> { todo!(); }
}

И для открытого:
impl Connection<Open> {
    fn close(self) -> Connection<Close> { todo!(); }
    fn write(&self, _data: &[u8]) { todo!(); }
}

Пишем конструктор:
impl Connection {
    fn new() -> Connection {
        Connection{ state: std::marker::PhantomData }
    }
}

Теперь всё готово для использования
fn main() {
    let con = Connection::new().open();
    con.write("Hello".to_owned().as_bytes());
    let con = con.close();
}

Об остальном позаботится компилятор. Вызвать два раза open или close невозможно (на том же C++ это запретить тяжело). Попытаться записать что-то в закрытое соединение не получится.
Остаются только философские вопросы использования. Н-р соединение может стать закрытым не по нашей воле. Или как вообще хранить объект соединение? Получается только в открытом состоянии (в закрытом возможно смысла не имеет).
То есть вопросы по сравнению с классической реализацией конечно есть, но и выгода тоже наличиствует. Лично я классически паттерн state реализовывал только однажды. После получившегося "переусложнизма" зарёкся когда-либо ещё писать подобные конструкции. Такую же технику попробовать можно. Тут дублирование минимально.

Код https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=49b593914d0a35583e64860a1b8f17e6
Оригинал на английском (и более подробно) можно послушать здесь
https://www.youtube.com/watch?v=_ccDqRTx-JU
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.