C# Design Patterns – Choosing the Right Pattern for Your Project

cdesign-patterns

scenario:

I have an entity called Member. Members fall into multiple types. Some types are below.

  • Supporter
  • Volunteer
  • Sponsor
  • Player

I can create class for each type and inherit from the base Member entity. But when a Member has more than 1 type in a given time, it is not the right way.

can I use decorator pattern to achieve this intent? Or what the best pattern to get this work?

EDIT :

Language I use is C#

Also different Member types can have additional methods, for example, Sponsor can have its own methods as Donate(), Or the Volunteer can have a method Subscribe() and so on. these thing have to be considered.

Best Answer

As usual, there are several different ways. Here are a few possible ideas for you to investigate:

Inheritance

I would not realize this via inheritance - especially not if you want multiple such roles for a member. Even with just one role, there's the composition over inheritance principle that tells you to avoid doing that if possible. It reduces your potential for reuse dramatically. Anyways, with your requirement that you want to be able to support multiple roles for a member, you would have to provide subclasses for each combination, which results in an exponential explosion of class combinations. Not very feasible.

Decorator

As you pointed out the decorator pattern would be one possible way, but would still require a lot of work in wrapping the original Member and providing all of its methods via the decorated object as well.

Composition

Composition is a straightforward way that you could use to add a role to a Member, if you can define a common interface for the roles, i.e., Supporter, Volunteer, etc. would implement the interface MemberRole and the Member class gets an attribute of type MemberRole (or a list thereof).

If, however, the roles each have different methods, composition doesn't work so well anymore (f.ex. a Supporter has support(), but a Player has play()), because you cannot find a common interface for the roles.

Traits/Mixins

As you didn't tell us which programming language you want to use, let me add one more option that would be interesting, but harder to realize in some languages. As an example, consider Scala with its support for traits. They are a perfect match for your problem, as you could do the following:

trait Supporter {
  def support = ...
}
trait Player {
  def play = ...
}
// and so on

val memberA = new Member with Supporter with Player
memberA.support // works fine
memberA.play // works fine
val memberB = new Member with Supporter
memberB.support // works fine
memberB.play // won't compile

Composing traits like this essentially saves you the exponential explosion mentioned above, as you do not need to provide a specific class for a MemberSupporterPlayer and such. An additional advantage is the type-safety shown above that ensures you cannot call methods from a role that your member does not possess.

For something similar in C# you can consider Mixins. See for example the remix project for this. They essentially allow the same kind of composition, but of course use a different syntax.