1

First of all I am going to give you a brief explanation of what i am after doing. I want to write a program that applies filters to an image using a strategy design pattern. I have read some documentations about the pattern and decided to use it like this.

First I will create an Interface called FilterStrategy which has one method called applyFilter.

After that I create 2 different classes, lets call them BeautifulFilter and UglyFilter that implement the interface above.

Then I will write a context class which has a private member of FilterStrategy and a setter method for two different strategies. And lastly one more method in which i call the applyFilter

In main my function I create a FilterStrategy and set the filter for UglyFilter and call the function.

Here is what I am asking. BeautifulFilter and UglyFilter has many common methods such as read image, write image, convolution and display... and there also some methods that are used by only one of the filters above. Where am I supposed to implement these methods? Should I duplicate my code in both of the filter classes?

3 Answers 3

6

I would implement a parent class for your filters eg FilterBase

This FilterBase would implement the read, write, convolution and display methods. Then when your classes BeautifulFilter and UglyFilter inherit from it, they would be able to access the methods themselves.

2

Here is what I am asking. BeautifulFilter and UglyFilter has many common methods such as read image, write image, convolution and display...

So far this sounds fine.

and there also some methods that are used by only one of the filters above.

And here's where it goes to hell.

Where am I supposed to implement these methods? Should I duplicate my code in both of the filter classes?

Look you can't have special methods that can only be called if it's the right type and use the strategy pattern. Or template method pattern or even naked inheritance. Polymorphism just doesn't work that way. You can't ask the using code to know what the type is.

My favorite example for this telling pets to speak. I like not having to tell a dog to bark or a duck to quack. I can just say pet.speak() and whatever pet that is figures out what to do. If I sometimes need silence I don't wrap the speak command in an if, I use a cat (otherwise known as the null object pattern). You tell it to speak and it ignores you (cause it's a cat). My cat can be carefully designed to quietly accept and ignore every possible message (or ignore just some of them). I can send my cat to anything that works with pets and things still work nicely without blowing up. However, my pet rock is another issue. You tell my pet rock to speak and it tears a hole in the fabric of reality by complaining that it doesn't know how to speak because I never taught it how. Now sure you can be careful and check for rocks before asking it to speak but it's easier to use cats. They're really good at doing nothing.

6
  • What if the special methods are private methods that only make sense in the implementation class? I think that's OK.
    – du369
    Oct 27, 2018 at 9:17
  • 1
    @du369 of course it is. Polymorphism is about the using code. What happens hidden inside is nobody else's business.Encapsulation is a good thing. Oct 27, 2018 at 9:22
  • So if I am understanding you correctly, your answer is about "not to pollute an interface with special methods that only make sense to some (not all) implementation". For that, I totally agree.
    – du369
    Oct 27, 2018 at 9:24
  • 1
    @du369 that's the principle to follow. But I'm also showing how to accommodate differences that tempt you to break it. Prefer abstract messages like speak() to bark(). Use them even if it's a cat that won't meow on command. Accept the message. Just don't meow. Design the class around how it will be used. Not around what you think it is. Oct 27, 2018 at 11:56
  • That is very insightful. Thanks for the explanation.
    – du369
    Oct 28, 2018 at 1:54
0

From what you describe context class should be concerned with loading/writing image and filter should be concerned only with changing image data. I believe image manipulation code will be complex enough.

So filter classes would have one method ApplyFilter() that takes image data as parameter and returns image data with filtering applied.

1
  • I think OP means the body of each applyFilter will involve calls to shared code
    – Caleth
    Oct 25, 2018 at 8:12

Your Answer

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

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