This is a pain in C# without creating a separate assembly and using the
internal modifier. Times like these I wish for a logical unit (and
corresponding access modifier) similar to packages in java. Or the C++
concept of friend classes.

As it is, I use something similar to your example. As written I think
your code has some problems with the specification "the objects should
not be created outside of one static function". For example,
1) clients can create a MyItfImplementorA simply by calling
MyItfImplementorA.Create(TheFactory.Instance())
2) clients can create a MyItfImplementorA by calling
MyItfImplementorA.Create(null)
3) clients can implement their own class which implements
IMyInterfaceFactory and call MyItfImplementorA.Create(myNewFactory)
Also, your factory singleton isn't thread-safe ;-)

The code below is a slightly tighter version of the same principle.

public interface IMyInterface { void Run(); }

public class MyClass: IMyInterface {
        private MyClass() {}
        public void Run() { /* whatever */ }
        public static MyClass Create( MyFactory factory ) {
                if (factory == null) throw new Exception("Nice try");
                return new MyClass();
        }
}

public sealed class MyFactory {
        private static MyFactory _instance = new MyFactory(); //
singleton
        private MyFactory() {}
        public static IMyInterface CreateMyInterface() {
                // logic for which concrete class
                // to instantiate goes here ...
                return /* for example */ MyClass.Create(_instance);
        }
}

It is now impossible for clients to create a MyClass without using
MyFactory.CreateMyInterface(). And note that MyFactory is sealed, so
clients can't extend it and pass in an instance of their descendent
class to MyClass.Create().

Cheers,

Isaac

> -----Original Message-----
> From: Moderated discussion of advanced .NET topics.
> [mailto:[EMAIL PROTECTED]] On Behalf Of Stoyan Damov
> Sent: 01 August 2002 09:23
> To: [EMAIL PROTECTED]
> Subject: Re: [ADVANCED-DOTNET] Need a C# pattern that returns
> an Interface
>
>
> Well, I guess it could look a little bit strange but it works and I
> can't come up with a better idea, and because I am not as
> articulate in
> explanations as I wish, here's the commented code:
>
>
> using System;
>
> namespace TestPattern
> {
>
> // the interface
> public interface IMyInterface
> {
>         void Run ();
> }
>
>
> // you'll get the idea below
> public interface IMyInterfaceFactory
> {
> }
>
>
> // an implementor
> public class MyItfImplementorA : IMyInterface
> {
>         // note, the constructor is private
>         private MyItfImplementorA () {}
>
>         public void Run ()
>         {
>                 Console.WriteLine ("Running MyItfImplementorA");
>         }
>
>         // see? only the factory is allowed to call this method
>         public static IMyInterface Create
> (IMyInterfaceFactory factory)
>         {
>                 return (new MyItfImplementorA ());
>         }
> }
>
>
> // another one
> public class MyItfImplementorB : IMyInterface
> {
>         private MyItfImplementorB () {}
>
>         public void Run ()
>         {
>                 Console.WriteLine ("Running MyItfImplementorB");
>         }
>
>         // see? only the factory is allowed to call this method
>         public static IMyInterface Create
> (IMyInterfaceFactory factory)
>         {
>                 return (new MyItfImplementorB ());
>         }
> }
>
>
> // this is the factory and it is singleton
> public class TheFactory : IMyInterfaceFactory
> {
>         private static TheFactory instance = null;
>         private static int x = 1; // no special purpose
>
>         private TheFactory ()  // private ctor (singleton)
>         {
>         }
>
>         public static TheFactory Instance ()
>         {
>                 if (instance == null)
>                         instance = new TheFactory ();
>                 return (instance);
>         }
>
>         // this is your static method
>         public static IMyInterface CreateInstance ()
>         {
>                 switch (x)
>                 {
>                         case 1:
>                                 x ++; // this is just to imitate your
> logic where different objects are created...
>                                 return MyItfImplementorA.Create
> (Instance ());
>                         case 2:
>                                 x --; // here too...
>                                 return MyItfImplementorB.Create
> (Instance ());
>                         default:
>                                 return (null);
>                 }
>         }
> }
>
>
> public class Test
> {
>         public Test ()
>         {
>         }
>
>         public void Run ()
>         {
>                 IMyInterface [] itfs = new IMyInterface []
>                 {
>                         TheFactory.CreateInstance (),
>                         TheFactory.CreateInstance ()
>                 };
>
>                 for (int i=0; i<itfs.Length; i++)
>                         itfs [i].Run ();
>         }
>
>
>         static void Main (string [] args)
>         {
>                 new Test ().Run ();
>         }
>
> }
>
>
> }
>
> Hope that helps,
>
> Stoyan Damov
>
> -----Original Message-----
> From: Michael Potter [mailto:[EMAIL PROTECTED]]
> Sent: Thursday, August 01, 2002 5:11 AM
> To: [EMAIL PROTECTED]
> Subject: [ADVANCED-DOTNET] Need a C# pattern that returns an Interface
>
>
> I have a static method that will return an object of IMyInterface. It
> will create the best 1 of many mutually exlusive objects that
> implement
> IMyInterface.  The object created depends upon the available hardware
> resources.
>
> The objects should not be created outside of the one
> static function. How do I hide the constructor of the
> objects (that implement IMyInterface) from the rest of
> the world and yet, allow them to be exposed to the one
> static creation method?
>
> Any ideas?
> Mike P
>
>
>
> __________________________________________________
> Do You Yahoo!?
> Yahoo! Health - Feel better, live better http://health.yahoo.com
>
> You can read messages from the Advanced DOTNET archive,
> unsubscribe from
> Advanced DOTNET, or subscribe to other DevelopMentor lists at
> http://discuss.develop.com.
>
> You can read messages from the Advanced DOTNET archive,
> unsubscribe from Advanced DOTNET, or
> subscribe to other DevelopMentor lists at http://discuss.develop.com.
>

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to