3

I need a pattern:

I'm using C#.

Say there are three actors; Jim, Pat, and Sally. Pat's job is to create an interface as a contract between Jim and Sally. Sally's job is to create a class that implements the interface and Jim's job is to write a class that consumes Sally's object.

Jim should not know about Sally's concrete object, only that it implements the common interface.

Pat needs to include in the contract a way for Jim to create an instance of Sally's concrete object but referenced as the interface.

There is no way to include a static method definition in either an interface or abstract class, so you can't do something like:

public interface IFoo
{
    public static IFoo CreateIFoo();
}

How can Pat write the contract to guarantee that Sally will create a method for Jim to create her concrete object referenced as the interface?

2
  • 2
    Factory pattern would probably help here. Either that, or you'd have to move the static method to a static helper class instead, but that wouldn't be in any way 'enforced' by the contract. Commented Jun 17, 2013 at 18:37
  • Thanks "Trust me", You point out my dilemma, there is no way to enforce the factory as a static method in a helper class. Commented Jun 17, 2013 at 19:08

2 Answers 2

1

If possible, ask for an instance of Sally:

class Jim 
{
    public Jim(Sally sally){ /* ... */ }
}

If, however, Jim needs to know WHEN to construct Sally, you can pass in a delegate:

class Jim
{
    private Func<Sally> _createSally.

    public Jim(Func<Sally> createSally)
    {
        _createSally = createSally;
    }

    public void ConsumeSally()
    {
        Sally sally = _createSally();
        /* ... */
    }
}

Simplest usage:

var jim = new Jim( () => new Sally() );

You don't need a class (Pat) to know how to instance sally, unless it really adds value to your code. Either way, you probably don't want Jim to know about Pat, so if Pat is needed this is what you'll want:

var jim = new Jim( () => Pat.GetSally() );
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Andre, I'm afraid I'm a little confused by your terms. Assuming that you mean that "Jim" is the class that Jim wrote and "Sally" is the class that Sally wrote that implements IFoo, then "Jim" doesn't know about the class "Sally", only the interface IFoo. and "Jim" can't create "Sally" directly. Also, if you mean that "Pat" is the interface IFoo, you can't instantiate "Pat" to call GetSally(). There is no class "Pat".
What I'm saying is that a class should not know how to build it's dependency, and this includes not knowing the factory (Pat's class). If Jim (class that consumes the dependency) knows about Pat's (the factory), you'll have a Service Locator, which is considered an anti-pattern.
If a class really need to know when to build it's dependency (although this is not common), wrap it in a delegate or in a Lazy<T> (C# 4+ only).
I'll try to improve my answer later, no time right now. Sorry.
0

Sounds like you need an abstract factory. In addition to IFoo, create an interface IFooFactory with the CreateFoo method. Give Jim an instance of an object that implements IFooFactory, and Jim would call the CreateFoo method. It could be either Sally or Pat's job to create the instance of the object that implements IFooFactory.

2 Comments

Thanks Michael, So as I understand it there will be an additional interface such as: public interface IFooFactory { public IFoo CreateFoo(); } Doesn't this just push out the problem to the factory? How does Jim get the concrete object of the IFooFactory that Sally creates?
@dtaylor Sally has some kind of FooFactory - the factory that implements IFooFactory, which is bound by contract to create IFoo interfaces. You can create the factory in-place or inject the concrete factory, the main point here is: if Jim wants IFoo from Sally, he can get it by calling IFooFactory.Create().

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.