Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Looks like Strategy pattern but unsure how to implement 3

Status
Not open for further replies.

zooxmusic

Programmer
Nov 24, 2004
96
US
Hi all,
I have 2 classes. One writes images to a file and another writes them to a db. This absolutely looks like the Strategy Pattern but I am unsure of how to implement it. The FileImageWriter will take a path of where to store it and the DbImageWriter will have to take the host, service_name, username and password. I am sure that both of them should take some kinf of interface like IImageWriter but I don't know exactly how to get this done.

Thanks in advance
Brian


Spend like you don't need the money,
love like you've never been hurt and dance like no one's watching!
 
Each implementation of IImageWriter will require different kinds configuration settings. You don't want the client to know which type it's using, so the client must not be aware of what kinds of settings each one uses. Therefore, the implementations themselves will have to be responsible for getting their config data from somewhere.

Possibly, the constructors of each implementation is where the config data is read from an external source.



[pipe]
 
Hmmm, Cause I am using a Servlet and the web.xml seems to be the perfect place to put the db connection information but only a servlet (as far as I know) can get its config file. Any comments?

Brian


Spend like you don't need the money,
love like you've never been hurt and dance like no one's watching!
 
Brian

The problem here is that they have different signatures, so you can't really share an interface or use an abstract class to implement Strategy.

Assuming you will normally store to the same path or database, perhaps you could rationalise the interface a bit by putting the path, host, service name, username, and password in an application config file? FileImageWriter and DbImageWriter could then get the information from config using private methods, and you'd only need to pass a string identifier on the interface to identify the image.

I don't know your requirements, but I'm not keen on storing images in databases. Because of their size, they bloat your tables and cause excessive logging, and you don't get any benefit as the image itself can't be indexed. Have you considered putting the image information (there are classes you can use to extract the metadata from JPEGs and EXIFs, for example) and the image file name on the database table(s), and storing the image as a file in an ../images directory somewhere? This gives you the best of both worlds. You get to search the DB when you look for images, but don't clog it up with multi-megabyte binary columns.

I guess you could store a small, heavily compressed JPEG thumbnail image of the full picture on the DB table to make your life a bit easier in the UI, if you need to return a list of candidate images resulting from a search.

And you could do all this using the same interface!

But I digress...

 
Thanx Steve,
I am not making the decision to store it in a db. I just have to do what I am told. I agree and I am currently saving them to a file and storing the path to that image in the db. BUT... the "other" developers here use Oracle Forms(I HATE THEM) and it is VERY limited so they believe that it will be faster to load the image from a db than a file. But who am I to say, I just work here. I am also sure no one here will ever read this post because not one single soul here is even trying to do things in an Object Oriented fasion.

Brian


Spend like you don't need the money,
love like you've never been hurt and dance like no one's watching!
 
Brian, you sound somewhat bitter there, my friend. I've been in similar situations and know how you feel. Take pride in the fact that you strive to learn ways of improving your knowledge and finding new / better ways of doing things.

Tim
 
Yes, encapsulate what changes into a family of algorithms. You already have 2 classes doing something similar, but in a different manner. They both do persistence.

With that said, employ a common Interface, "IImageWriter" that exposes Persist() behavior.

Steve is right, in what he says: >>>
"Assuming you will normally store to the same path or database, perhaps you could rationalise the interface a bit by putting the path, host, service name, username, and password in an application config file"
-Steve


With configuration settings like that, the client that is using the IImageWriter is shielded from knowing where and how persistence is accomplished.

The client code now can look something like:


anImageWriter.Persist(anImage);

anImageWriter can be configured at app time using some form of dependency injection so that the client dont have to manage/hardcoded concrete instantiations.



 
Ed

'dependency injection' isn't a term I've heard before, (except perhaps in a recreational drug use context). Can you elaborate, please?
 
Hi Steve, Dependency injection is a pattern most of us follow without realizing it. It deals with the principal of breaking dependencies between a client and a concrete object, but it evens goes further than just that.


>>[stay with me here, you might already know this but it's a good warmup for members new to oo principals]<<


For example, in the original post above, zoo faced a rather common architectural problem. He had 2 different ways of persisting an image(object). So he followed "Factor out what varies" and ended up with 2 concrete classes that does persisting in their own unique ways. Now each of the 2 classes is very cohesive, has a single responsibility and only one reason to change in the future.

Now, with those 2 classes at hand, he has to figure out how to correctly utilize them. I am pretty sure a client* will need to request the services of either one of those implementations at runtime, but should the client explicitly instantiate an instance of either? No. That will just defeate the whole purpose of pluggability, it leads to hardcoding and client code changes as new implementations come along. Robert C. Martin explained the Dependency Inversion Principal as:

"High level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details, details should depend on abstractions"

In other words, create an abstraction that represents the family of concrete low-level implementaions. Let each low-level module inherit or implement an interface of the abstraction. That will solve the latter "details should depend on abstractions".

So you end up with:

[IImageWriter]
^
|
|
[DbWriter] [FileWriter]



With that said, the client can now use the IImageWriter without having to worry about the low-level details of how images are being written, which solves the former "High level modules should not depend on low-level modules"

so now you end up with a diagram where the client is refering to an abstraction/Interface and the low-level details are referring/implementing that abstraction:


[aClient]
|
|
v
[IImageWriter]
^
|
|
[DbWriter] [FileWriter]



That explains the part where he says, "Both should depend on abstractions". IImageWriter has a very important purpose here, it forces the client to think at a higher level and not worry about how detailed things are done, it also encapsulates and hides all of the various implementations of persisting images and prevents the client from changing as new low-level modules are written. So it makes the design open for extension but closes the client from changing.

Now thats all fine and dandy but how exactly does the client use a specific implementation? I said earlier that the client should only rely on the high level abstraction and not the low level modules, but the client still needs a way to get a reference to an instance of a specific low level module. This is where you inject those dependencies.

Normally the client code might look like:

class ImageSaver {
IImageWriter anImageWriter = new FileImageWriter();
anImageWriter.Persist(anImage);
}

or


class ImageSaver {
IImageWriter anImageWriter = new DbImageWriter();
anImageWriter.Persist(anImage);
}


This solves just half of the problem, now the hardcoding of those concrete instantiations must be pulled out so that later when joe blow writes yet another low level module, it can be plugged in and work without any changes to the client.

Dependency Injection comes in 3 forms:
type 1 IoC (interface injection)
type 2 IoC (setter injection)
type 3 IoC (constructor injection)

And Martin Fowler does a great job at explaining this in his article:

There are also some mixing variations like global registries and reflection that solve these issues. To be honest, I use Reflection, Activator.CreateInstance("FileImageWriter") in my apps to inject dependencies and remove anything hardcoded.

In my next project I plan to make use of reflection with Registries to solve this issue.
 
Damn I gots so much to learn.

Thanks guys. Still don't get it to the level to start designing but I think a couple of times through and I will have it.

Brian


Spend like you don't need the money,
love like you've never been hurt and dance like no one's watching!
 
Hi zoo,
Don't feel like your left in the dust. I am still actively learning as well.

It's interesting that everytime I learn something new, i find that i have to do more research about what i just learned, which leads me learning something new, which leads to more reasearch, which leads to learning something new...and on and on..

I'll tell you this much, if you are naturally self motivated and devoted to the princiapals, it's a never ending curve but a fun one.

I enjoy my career, if the world didn't revolve around the concept of money, I would still be doing it.

EdwardJS

 
Thanks Ed

Spend like you don't need the money,
love like you've never been hurt and dance like no one's watching!
 
Ed

Thanks for the feedback (most useful), and the pointer to the Fowler article.
 
How do you feel about the use of an Abstract Factory to solve the dependancy issue? Thus defer all knowledge of the actual concrete implementations to a single class that has this as its purpose, and keep plugability. I use it quite a bit and am happy with the way it works.

I would be interested to hear any thoughts about this.
 
jby1,
As an example how would that work? Where would I store the database/image path stuff? A properties file? Sorry for my ignorance for some reason I am stuck on leaving it in the web.xml. But I can see that being a problem if it is not a servlet, so I need to get rid of that idea.

Spend like you don't need the money,
love like you've never been hurt and dance like nobody's watching!
 
IImageWriter anImageWriter = aFactory.GetWriter();
anImageWriter.Save();

GetWriter can look at your application config file for the configured instance of concrete writer to return
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top