views:

409

answers:

5

I like the idea of "programming to interfaces" and avoiding the use of the "new" keyword.

However, what do I do when I have two classes that have the same interface but are fundamentally different to set up. Without going into detail about my specific code, I have an interface with a method, "DoStuff". Two classes implement this interface. One is very simple and requires no initialisation to speak of. The other has five different variables that need to be set up. When combined, they allow for literally millions of ways for the class to work when DoStuff is called.

So when do I "new" these classes? I though about using factories but I don't think they are suitable in this case because of the vast difference in setup. (BTW: there are actually about ten different classes using the interface, each allowing the formation of part of a complex pipeline and each with different configuration requirements).

+1  A: 

Regardless of what you use, at some point you're going to have to construct instances of your classes in order to use them, there's no way around that.

How to go about doing that depends on what you want to accomplish, and the semantics of those classes.

Take the class you mention with those fields.

Can those fields be read from somewhere? A configuration file, as an example? If so, perhaps all you need is just a default constructor that initializes those fields from such a configuration file.

However, if the content of those fields really needs to be passed in from the outside world, there's no way around that.

Perhaps you should look at a IoC container and Dependency Injection?

Lasse V. Karlsen
+6  A: 

I think you may be misunderstanding the concept of programming to interfaces. You always have to use the new keyword in object oriented languages to create new instances of objects. Just because you program to interfaces doesn't remove that requirement.

Programming to an interface simply means that all your concrete classes have their behavior defined in an interface instead of in the concrete class itself. So when you define the type of a variable, you define it to be the interface instead of a concrete type.

In your case, just implement DoStuff in your concrete classes as each class needs it implemented (whether doing it simply or with 10 other initialized objects and setup). For example, if you have an interface IInterface and class SomeClass which implements IInterface. You might declare an instance of SomeClass as such:

IInterface myInstance = new SomeClass();

This allows you to pass this instance around to other functions without having to have those functions worry about the implementation details of that instance's class.

Marc W
You do not always need to use the new keyword - C++, for example, has no such requirement.
anon
The reason for my question is that I am learning about and trying to apply the SOLID principles. I've read several times that the "new" keyword should be avoided as much as possible by using factories, etc. Clearly there are occasions where it is required but have I misunderstood the principles?
You only really need to use factories if they are really necessary. I've found that more often than not, they are too heavyweight. I have never heard of avoiding the "new" keyword. That seems silly to me. I'd suggest picking up a copy of the Gang of Four book on design patterns to learn more about factories.http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612
Marc W
The problem with using “new” is that it binds a reference to the concrete implementation class at that point. While that's sometimes A-OK, often you need more flexibility than that. That's why you use the Factory pattern (though arguably that's just moving the problem around as the factory has to be created somewhere…) Dependency Injection containers are factories on steroids that put the concretization of all the interfaces in conceptually one place; you still have the bindings, but now they're not scattered over every damn class in the program.
Donal Fellows
+2  A: 

Well you really have 3 options. Use new, use a factory or use an DI container. With a DI container your five variables would most likely need to be in a configuration file of some sorts.

But to be completely honest it sounds like you're making your life harder than it needs to be by forcing yourself into a corner. Instead of coding to some ideal, rather code in a manner which best facilitates solving the problem at hand. Not saying you should do a hack job of it, but really, saying you don't want to use new, that is really making your life harder than it needs to be...

A: 

If you are passing that many configuration parameters into your class it may have too many responsibilities. You should look into breaking it up into smaller classes that only have a single responsibility.

Avoiding the new keyword can be valuable because it creates a dependancy on the implementing class. A better solution would be to use Dependancy Injection.

for example

public interface IDoStuff
{
    void DoStuff();
}

public class DoStuffService
{
    private IDoStuff doer;

    public DoStuffService()
    {
        //Class is now dependant on DoLotsOfStuff
        doer = new DoLotsOfStuff(1,true, "config string");
    }
}

public class DoStuffBetterService
{
    private IDoStuff doer;

    //inject dependancy - no longer dependant on DoLotsOfStuff
    public DoStuffBetterService(IDoStuff doer)
    {
        this.doer = doer;
    }
}

Obviously you still have to create the IDoStuff object being passed in somewhere. An Inversion of Control (IoC) container is a good tool to help with implementing this. Here is a good tutorial for Castle Windsor Container if you are interested in learning more. (There are many other IoC containers, I just happen to use this one.)

The example in your question was very abstract, so I hope this answer is helpful.

ebrown
A: 

If I got you right the problem is with different initialization you need to provide for these 2 classes that have same interface. One dont need anything, and the other need to get some params and call some complex initialization. If Im right, you should use have a constructor that gets InitializationParameter. Both classes should get it. One with simple interface do not need to get anything from it. Other that needs params will get them from it.

If it`s all about initialization you can use factory, just ask it for some interface providing this init parameter and factory will create, init and return you the object according to the values you provided.

If something is not clear - please ask.

Yaroslav Yakovlev