Pull to refresh

Comments 24

Не понял толком отличия forwarder'а и прочих, поэтому повторил как понял.
Опять же неясно, зачем нужны forwarder'ы, если основная идея в цепочности.
У меня при возврате Just v сообщение идёт дальше по цепочке, при возврате Nothing цепочка прерывается. А route нужен, чтобы ответвить сообщение в другую цепочку.

module Event (
    ) where

import Prelude hiding (id, (.))
import Control.Category

data Node a b = Node (a -> IO (Maybe b))

instance Category Node where
    id = Node $ return . Just
    (Node g) . (Node f) = Node $ \v -> do
        f v >>= maybe (return Nothing) g

endnode :: (a -> IO ()) -> Node a ()
node :: (a -> IO ()) -> Node a a
run :: Node a b -> a -> IO (Maybe b)
run_ :: Node a b -> a -> IO ()

endnode f = Node $ \v -> f v >> return Nothing
node f = Node $ \v -> f v >> return (Just v)
run (Node f) v = f v
run_ (Node f) v = f v >> return ()

server = endnode putStrLn
route to = node $ run_ to
forward to = node $ run_ to
network to = node $ run_ to

test = run test' "correct" where
    logmsg = node $ \s -> putStrLn ("log: " ++ s)
    test' = logmsg >>> test'' >>> server
    test'' = route (network fw2) where
        fw2 = forward fw1
        fw1 = forward serv
        serv = server
За что такая подсветка???
Отличия в потенциально возможном различном поведении.
хаскелл-джедай..? :)

А вы, собственно, что именно куском кода-то сказать хотели?
Си++ код тоже можно записать так же компактно, без иерархии и десятка наследуемых друг от друга классов.
Интересный паттерн. Спасибо за пищу для мозга. Но не очень-то наглядный пример, особенно для людей не знающих C++. Комментариев в коде нет, что особенно напрягает. Т.е. суть ясна, а реализация — нет.
да-да.
было бы гораздо круче использовать что-нибудь более абстрактно-понятное.
а начинаешь залипать в код, вместо осмысливания идеи.
Плюсую. Хоть и знаю С++, читать все равно напряжко. Голосую за то, чтоб в статье был псевдокод и ссылка на реализацию
Хорошо. А что вы хотите видеть в примерах?

Абстрактный класс Handler, два наследника Handler1, Handler2, сообщение Message которое обрабатывается одним из обработчиков — handle(Message message)? Это ровно четыре строчки кода и скукота. Я пытаюсь дать читатели интересный и сложный пример, поняв который он лучше осознает/запомнит материал.
Давайте еще хэллоуворлды объяснять с помощью 20-ти классов с шаблонами и виртуальным наследованием, а то скукота
Давайте!

Раз уж мы изучаем шаблоны проектирования, давайте пытаться думать и изобретать ;)
Да, C# или Java, например
Да каккая разница какой язык?

Я писал примеры к постам на различных языках — на Python, Java, C#, C++ и т.д.

Так случилось что этот паттерн я реализовал на C++. Если вы перейдете по первой ссылке, найдете примеры на других языках.
Хорошее и достаточно детальное описанное применения паттерна (комментариев правда маловато, как выше верно заметили). «Бандитский» пример менеджера справки из книги гораздо более абстрактный — пришлось два раза перечитывать, чтобы понять структуру распределения обязанностей между объектами.
Я тоже не так давно применил этот паттерн в разработке одного приложения с использованием SCSF. У меня ситуация была следующая: есть список Workspace вложенных друг в друга. ShellWorkspace с кнопкой Back и Next и Print, в него встраивается RootWorkspace c кнопками категорий. А при нажатии на одну их кнопок категорий в RootWorkspace встраивался ContentWorkspace. Обработку навигации я делегировал специальному менеджеру-сервису а вот обработку кнопки Print реализовал с помощью паттерна Chain of Responsibility. Т.е. команду мог обрабатывать только конкретный ContentWorkspace. Поэтому все вышележашие просто реализовывали так:
public bool Print()
{
    IContentView view = this.Workspace as IContentView;

    return view != null ? view.Print() : false;
}


И последний в списке экземпляр конкретного ContentView:
public bool Print()
{
    bool result = false;

    // Printing code...

    return result;
}
И разместите пожалуйста в этой статье ссылку на книгу, или оригинального описания этого паттерна. А то непосвященные будут читать и думать, что это вы придумали этот паттерн :) Нехорошо это — на святое замахиваетесь :)
Боже упоси читать статью о паттернах непосвященным людям :) По этой ссылке переходят только те для кого слов GoF не просто бесмысленное сочетание букв.
Ну а если человек никогда об этом не слышал? Надо же дать ему шанс :)
Наверное на этом можно заканчивать комментарии.
ISBN 978-5-469-01136-1
всем советую, книга имеет ограничение по возрасту (читать от 3-х лет + одного большого проекта, переписанного второй раз). ;-)
интересно, спасибо. Только вместо диаграммы классов было бы интереснее увидеть диаграмму деятельности
А поясните, пожалуйста, почему

RequestHandler(RequestHandler *successor): successor(successor) { }

Насколько я понимаю, тут вызов конструктора этемента successor, но ведь у нас есть только указатель на него (который получаем в сончтруированном виде), не надо ли вместо него написать

RequestHandler(RequestHandler *successor) { this.successor = successor}
Не обязательно. Это лишь сокрашенная форма записи.

Можно было написать и так — RequestHandler(RequestHandler *successor) { this->successor = successor}
Стремление внедрять шаблоны это хорошо, главное понимать их правильно ( не как большинство понимает MVC).
Так вот:
«Возможен еще вариант обработки и последующей передачи. „
Это не “возможен» — это главный мотив использовать этот шаблон. Если у вас нет необходимости совместной обработки несколькими обработчиками приходящего сообщения — то его применение проигрывает простому Map [Тип сообщения] -> [Экземпляр класса с интерфейсом обработчика] как по понятности/количеству кода, так и по скорости работы (обычно не так важно)

Отличное замечание!

Спс. Я действительно должен был акцентировать на этом внимание.
Спасибо за статью.
Хороший пример использования — фрейморк Netty (Java), обработка запроса и ответа.
Only those users with full accounts are able to leave comments. Log in, please.