2

I am considering using the Delegate Pattern to get some data necessary for an operation. There are a few different pieces of data that the algorithm needs to run, but they all have default values that can be used if they aren't explicitly set.

If I were to use the delegate pattern, I would define an interface that defines a function for each piece of information that the algorithm would then use to retrieve the data as it needs to.

The other option I see is to have setters on the algorithm object so that those properties can be set explicitly instead of waiting for it to be requested through the delegate pattern.

There are many advantages to using the delegate pattern, but I feel that many of them don't really apply to my situation. One of the biggest things is that it eliminates the need to make specialized subclasses of the object, but in my case, using setters also removes this need.

Also, the delegate pattern allows reuse of delegates like "configurations." If I use setters, everything will have to be explicitly set whenever reconfiguring (instead of just changing delegates around).

I would definitely lean towards using the delegate pattern, my only issue is that this is a public interface that will be used by people who aren't necessarily familiar with the pattern. I feel that using setters would be a more natural way for someone to do it without knowledge of design patterns.

A very simple example of what I am trying to do would be the following:

I have an algorithm that is going to determine if a certain range of characters exits in a string. The configurable options of the algorithm are:

  • First character (e.g. "k" )
  • Last Character (e.g. "p" will make it search for k,l,m,n,o and p )
  • number of characters out of range that need to match

So If I have the string "stack overflow" searching with a character range of "k-p" requiring that at least 4 characters match, it should return true because it contains "k","o","l", and "o".

Using the delegate pattern it would look this this (not necessarily the most efficient):

char startRange = delegate.startChar();
char endRange = delegate.endChar();
int targetCount = delegate.charCount();
int currentCount = 0;
for( char c in targetString )
{
   if( c >= startRange && c <= endRange )
   {
       currentCount++;
       if( currentCount == targetCount )
            return true;
   }
}
return false;

Otherwise the algorithm would require that member functions and variables are defined to set and store those values. The algorithm would look like this.

int currentCount = 0;
for( char c in targetString )
{
   if( c >= mStartRange && c <= mEndRange )
   {
       currentCount++;
       if( currentCount == mTargetCount )
            return true;
   }
}
return false;

The variables may or may not be changed often, and there will definitely be reuse of those variable configurations.

Are there any advantages of the delegate pattern that I am missing? Are there any disadvantages of using setters that I am missing? Any other comments or suggestions?

Thanks!!

4
  • I am not 100% sure that you understand what the delegate pattern is supposed to do, but I am not 100% sure that I understand what you are trying to do. The delegate pattern is suppose to hide or abstract something away. For example suppose I want to print something. Does the application care if print means write to disk, send to printer, or write to serial port? Probably not. What exactly are you are trying to abstract?
    – Pemdas
    Apr 28, 2011 at 1:49
  • I just edited my question to give a very simplified version of what I am trying to do. I feel your print example is more of a "Strategy" pattern where you have one abstract algorithm with multiple concrete implementations. It is definitely very similar, but I think the key difference for me is that I am only changing out data supplied to the algorithm, not the algorithm itself. My "algorithm" will be private, but the data that it is acting with, is public. I am trying to separate those to things in a clean manner. Sorry if I am not being completely clear!
    – drewag
    Apr 28, 2011 at 2:14
  • You want to instantiate an algorithm with certain initial values and reuse that instance in several different locations, where the only difference is the "targetString"? Strategy (or Command) pattern seems most useful for this. Apr 28, 2011 at 21:50
  • I feel strategy applies more to changes in business logic, it doesn't account for data changes. In my case, it is one unified algorithm that uses different data in a uniform way.
    – drewag
    Apr 28, 2011 at 23:28

2 Answers 2

1

http://c2.com/cgi/wiki?OccamsRazor

When faced with this kind of design decision always do the following.

  1. Write unit tests for the simplest concrete thing that will work.

  2. Write the simplest concrete thing that works.

  3. Add comments for some alternatives that might be useful in some potential future.

Stop solving this problem and move on. Don't over-solve.

Until you are forced to use the more complex solution, avoid it.

Until you have three places that can be combined, don't waste too much time refactoring. Two copies of similar code is not a sin. (Copy and paste of identical code is always evil.) A third copy of similar code means refactoring might be in order.

5
  • You make a really good point. Unfortunately, I already need a complex solution. My algorithm will have somewhere between 3 and 7 specific configurations that are used often, plus it needs to have the ability to make highly custom configurations right from day 1 that I start to develop it.
    – drewag
    Apr 28, 2011 at 23:25
  • 1
    @drewag: Nothing changes. Build concrete first. Refactor only after you have the concrete things working. Avoid overdesign at all costs. "custom configurations right from day 1" doesn't really exist. On day 1, you have no idea what the real range of customization is. Been there. Done that. Tore it out and replaced it twice because it was too complex.
    – S.Lott
    Apr 28, 2011 at 23:30
  • In my case I will have a gui that will allow the user of the application to specify all of the options that already exist for a third party library that I am using in the background. The design i am doing IS for a real range of customization. This is actually the second design of one of the tools that will use the framework. I have also been using this same background API for years so I know it extremely well. It is not a matter of designing for unknown use cases, but designing for many known, concrete use cases.
    – drewag
    Apr 29, 2011 at 0:50
  • 1
    @drewag: If the design is already dictated, I fail to understand why the question was asked in the first place.
    – S.Lott
    Apr 29, 2011 at 0:51
  • the design isn't dictated, only the requirements for what the framework should do is dictated. I am trying to design a flexible framework that provides a clean api for using this background API. The background API is in pure c and not at all object oriented, my design is essentially an object oriented wrapper with some extra functionality on top.
    – drewag
    Apr 29, 2011 at 0:58
0

I don't think this is a good application of the delegate pattern. It looks like you are using the delegates to supply a simple piece of data, this is overkill. You would typically use delegates when you need to supply functionality. So, go with the simple property based approach here I think.

2
  • Thanks for your input! This was a simplified version of the algorithm I am using. In fact, my algorithm is very complicated and has nothing to do with string parsing. I wanted to just give an example to make it more clear what I was saying, but of course the simplistic nature of the example changes the pattern that would be needed.
    – drewag
    Apr 28, 2011 at 23:19
  • Many good examples of the delegation pattern (e.g. 'UITableViewDataSource' from the iOS API) supply both data and functionality. I don't know if this is an anti-pattern or what, but I guess that the only benefit you can have from such a configuration is that you can supply many changes at once, without calling setters to sync two objects. (e.g. '[tableView reload]' and you're done) Jul 13, 2011 at 18:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.