Broker Chain

Hi,

I'm reading Design Patterns in Modern C++ by Dmitri Nesteruk (I'm not sure I can recommend it, but I bought it, so I should read it. Its chock full of errors) and I just finished a chapter on Chain of Responsibility (CoR) -- Broker Chains.

I understand the concept of a broker chain is to give multiple components a chance to apply/mutate some object as it's passed through the chain, but the example they gave in the book was a bit trite and confusing, so I'm just curious what a "real-life" application of the design pattern might be, AND/OR if you have any resources that helped the pattern "click" for you. I did a quick google search on Broker Chain design patterns and it's basically coming up with the same example in the book.

The example they gave in the book is similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <string>
#include <boost/signals2.hpp>

using namespace boost::signals2;

struct Query; 

struct Game
{
	signal<void(Query&)> queries;
};

struct Query
{
	std::string creature_name;
	enum Argument { attack, defense } argument;
	int result;
};

class Creature
{
public:
	std::string name;

	Creature(Game& game, std::string name, int attack, int defense)
	:game{game}, name{name}, attack{attack}, defense{defense}
	{

	}

	friend std::ostream& operator<<(std::ostream& os, const Creature& creature)
	{
		os << creature.name << std::endl;
		os << creature.get_attack() << ", " << creature.defense << std::endl;
		return os;
	}

	int get_attack() const
	{
		Query q{ name, Query::Argument::attack, attack };
		game.queries(q);
		return q.result;
	}
private:
		Game& game;
		int attack, defense;
};

class CreatureModifier
{
	Game& game;
	Creature& creature;
public:
	CreatureModifier(Game& game, Creature& creature)
	: game{game}, creature{creature} { }

};

class DoubleAttackModifier : public CreatureModifier
{
	connection conn;
public:
	DoubleAttackModifier(Game& game, Creature& creature)
	: CreatureModifier(game, creature)
	{
		conn = game.queries.connect([&](Query& q) {
			if(q.creature_name == creature.name &&
				q.argument == Query::Argument::attack)
				q.result *= 2;
		});
	}

	~DoubleAttackModifier() { conn.disconnect(); }
};


int main()
{
	Game game;
	Creature goblin{game, "Strong Goblin", 2, 2};
	std::cout << goblin << std::endl;

	{
		DoubleAttackModifier dam{game, goblin};
		std::cout << goblin << std::endl;
	}

	std::cout << goblin << std::endl;

}
I might have seen something of this nature with a message filter; the messages were outgoing, and various components had opportunity to add something to the message. At receiving end, corresponding components in a chain were passed the message and had opportunity to extract data from it.

The user could configure the chains themself (and the order of the filters), and the different filters didn't need to have existed when the program was first written. They could be added afterwards.

There are other ways to do the same thing, but it had its place.
Topic archived. No new replies allowed.