C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

design Q: override | strategy pattern | function object

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Marlene Miller
Guest





PostPosted: Thu Mar 17, 2005 2:31 am    Post subject: design Q: override | strategy pattern | function object Reply with quote



Hello.

I want to allow variations of a class, so that my event objects can use
different algorithms to select the next server. I am new to OO. I've read
about various ways to do things. They all work. But I don't know how to
choose.

Question: Would you please offer some guidelines or insights or reasons on
how you would choose?

1. Create a derived class and override the select function.

class E1 {
public:
void f() { S* s = select(); ... }
protected:
virtual S* select();
};

class B : public E1 {
S* select();
};

2. The strategy pattern - a family of algorithms with a common interface.

class C { //strategy interface
public:
virtual S* select();
};

class D : public C { //a special algorithm
public:
S* select();
};

class E2 {
C* c;
public:
E2(C* cc) : c(cc) {}
void f() { S* s = c->select(); ... }
};

3. The strategy pattern using function objects.

class SelectS {
public:
virtual S* operator()();
};

class FixedS : public SelectS {
public:
S* operator()();
};

class E3 {
SelectS* ss;
public:
E3(SelectS* p) : ss(p) {}
void f() { S* s = (*ss)(); ... }
};

Thank you. - Marlene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alf P. Steinbach
Guest





PostPosted: Thu Mar 17, 2005 12:38 pm    Post subject: Re: design Q: override | strategy pattern | function object Reply with quote



* Marlene Miller:
Quote:

I want to allow variations of a class, so that my event objects can use
different algorithms to select the next server. I am new to OO.

Bah, I suspect you're the first AI the military have allowed to access
the internet -- the "my event objects" rather gives it all away...


Quote:
I've read
about various ways to do things. They all work. But I don't know how to
choose.

Question: Would you please offer some guidelines or insights or reasons on
how you would choose?

1. Create a derived class and override the select function.

class E1 {
public:
void f() { S* s = select(); ... }
protected:
virtual S* select();
};

class B : public E1 {
S* select();
};

Here you code the server selection as part of the event object type
(assuming "E" stands for "Event"): do you really want the events to
have hardcoded server selection, whatever "server selection" means?

Where or by what are the events received?

Where's it natural to have that responsibility (server selection) placed,
whatever it means?

As a general rule event objects shouldn't do anything on their own, except
support of being event objects.

They should just serve as short communications from source to destination,
invoking responses in the destination object(s), and they don't seek out
their destinations (if that's what "server" is), they're sent directly there.


Quote:
2. The strategy pattern - a family of algorithms with a common interface.

class C { //strategy interface
public:
virtual S* select();
};

class D : public C { //a special algorithm
public:
S* select();
};

class E2 {
C* c;
public:
E2(C* cc) : c(cc) {}
void f() { S* s = c->select(); ... }
};

This seems like a misapplication of the strategy pattern: the server
selection (whatever that means) is still part of the event object, nothing
gained, points lost on more complexity to achieve the same as before, except
if you really need to specify server selection per event _object_ rather than
per event object class.


Quote:
3. The strategy pattern using function objects.

class SelectS {
public:
virtual S* operator()();
};

class FixedS : public SelectS {
public:
S* operator()();
};

class E3 {
SelectS* ss;
public:
E3(SelectS* p) : ss(p) {}
void f() { S* s = (*ss)(); ... }
};

Same comment as above.

The main question isn't what mechanism to use to put server selection
(whatever that means) into the event objects.

The main question is whether it really makes sense to have it there.


Quote:
Thank you. - Marlene

You're welcome.

Btw., look up the visitor pattern.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Antoun Kanawati
Guest





PostPosted: Thu Mar 17, 2005 12:51 pm    Post subject: Re: design Q: override | strategy pattern | function object Reply with quote



Marlene Miller wrote:
Quote:
Hello.

I want to allow variations of a class, so that my event objects can use
different algorithms to select the next server. I am new to OO. I've read
about various ways to do things. They all work. But I don't know how to
choose.

Question: Would you please offer some guidelines or insights or reasons on
how you would choose?

1. Create a derived class and override the select function.

class E1 {
public:
void f() { S* s = select(); ... }
protected:
virtual S* select();
};

class B : public E1 {
S* select();
};

2. The strategy pattern - a family of algorithms with a common interface.

class C { //strategy interface
public:
virtual S* select();
};

class D : public C { //a special algorithm
public:
S* select();
};

class E2 {
C* c;
public:
E2(C* cc) : c(cc) {}
void f() { S* s = c->select(); ... }
};

3. The strategy pattern using function objects.

class SelectS {
public:
virtual S* operator()();
};

class FixedS : public SelectS {
public:
S* operator()();
};

class E3 {
SelectS* ss;
public:
E3(SelectS* p) : ss(p) {}
void f() { S* s = (*ss)(); ... }
};

The difference between 2 and 3 is purely syntactic.

The first approach provides the basis that enables the second technique
(virtual functions, common interface).

In the second approach, you have two objects related by a reference,
so you have to consider the possibility of the C instance being shared,
also, you need to manage its lifetime to avoid dangling references.

Note that sharing the C resource may be a feature or a bug
depending on the nature of your problem space.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Mike Jolley
Guest





PostPosted: Thu Mar 17, 2005 12:52 pm    Post subject: Re: design Q: override | strategy pattern | function object Reply with quote


"Marlene Miller" <marlenemiller (AT) worldnet (DOT) att.net> wrote

Quote:
1. Create a derived class and override the select function.

class E1 {
public:
void f() { S* s = select(); ... }
protected:
virtual S* select();
};

class B : public E1 {
S* select();
};

This allows the derived class to make a choice about how to implement
the algorithm, but the base class is in charge of the interface. This has
been called "template method" but people seem to agree the name
should be changed. Anyway, it's a good idea to separate the interface
from the implementation and this pattern helps do that.

Quote:
2. The strategy pattern - a family of algorithms with a common interface.

class C { //strategy interface
public:
virtual S* select();
};

class D : public C { //a special algorithm
public:
S* select();
};

This does the same thing, but now the virtual function is public for no
particular reason.

Quote:
class E2 {
C* c;
public:
E2(C* cc) : c(cc) {}
void f() { S* s = c->select(); ... }
};

This is an example how how patterns 1) or 2) might be used
polymorphically.

Quote:
3. The strategy pattern using function objects.

class SelectS {
public:
virtual S* operator()();
};

class FixedS : public SelectS {
public:
S* operator()();
};

class E3 {
SelectS* ss;
public:
E3(SelectS* p) : ss(p) {}
void f() { S* s = (*ss)(); ... }
};

This is closer to 2) than 1) because the operator is public and
virtual. From the user's point of view it seems a lot different because
he doesn't have to remember the name of a function, just that the
object acts like a function by supplying ().

How to use these things depends on how trivial the classes are, and
mostly how much state data is stored by objects of the class. If it's
only enough state to make it useful to chain calls to this one member
function, you're looking at a good design. If it's more data than that
or if there are other public member functions, consider sticking to 1).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Gareth
Guest





PostPosted: Thu Mar 17, 2005 1:08 pm    Post subject: Re: design Q: override | strategy pattern | function object Reply with quote

Marlene Miller wrote:
Quote:
Question: Would you please offer some guidelines or insights or
reasons on
how you would choose?

Marlene,

If I were designing this system, the first approach I would drop would
be the override. Imagine that, in future, you want to write a new
event C, which uses the same selection algorithm as B, but has
otherwise different behaviour. Using approach 1, you have to duplicate
the code for the selection algorithm.

Your other two approaches allow you to abstract this functionality away
into a separate class, and therefore offer a cleaner design.

As for the choice between 2 and 3, well, there isn't one really.
Formally speaking, C/D are functors as well; the only distinction from
FixedS/SelectS is the name of the function being called. This would
only be important if you were passing the functor to an algorithm (such
as one from the STL) which expected it to define operator().

One more approach you may wish to consider is a policy-based design.
This would be similar to the functor method, but instead of your events
aggregating a pointer to the base algorithm class, you would templatise
them on the selection policy. For example:


struct Algo1
{ static S* select(); };


struct Algo2
{ static S* select(); };


template<class SelectionAlgorithm>
class Event {

S* server;
public:

void get_next_server()
{ server = SelectionAlgorithm::select(); }
};


// Then choose the desire algorithm when you instantiate your events
Event<Algo1> event;


Whether this is feasible depends on whether you need to change the
algorithm at run-time. If not, the policy approach should offer better
performance as it obviates the need for the virtual function call. On
the other hand, whenever you want to use a new algorithm, you need to
recompile all event-using code.

Hope that helps,
Gareth


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.