Factory method

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mark

    Factory method

    I have an abstract class, and a set of classes that inherit from my abstract
    class. The fact that it is abstract is likely irrelevant. I have a static
    factory method in my abstract class that creates subclasses. The
    constructor in my subclasses must be able to call the constructor in my base
    class. For the factory method in my abstract class to call the constructor
    on my subclasses, the constructor in the subclass MUST be public (or
    internal). They cannot be private or protected. However, doen't that
    basically defeat the purpose of factory? I'd love to be able to make all
    these constructors private or similar so that someone can't create subclass
    instances without using the Factory. If this was all in a separate DLL, I
    suppose I'd be saved by "internal", but we have small team of developers
    working on projects where that type of seperation really shouldn't be
    necessary.

    Suggestions? Code sample below ...

    Thanks in advance.

    Mark


    public abstract class MyBase
    {
    protected string first;

    public MyBase(string first )
    {
    this.first = first;
    }

    public static MyBase Factory(int stateId)
    {
    switch (stateId)
    {
    case 700:
    return new MySubClass1(fir st);
    default:
    throw new Exception("Bogu s code!");
    }
    }
    }


  • James Curran

    #2
    Re: Factory method

    Well, yes, but then, having the base class have any knowledge at all
    it's derived classes defeats the purpose of OO.

    --
    --
    Truth,
    James Curran
    [erstwhile VC++ MVP]

    Home: www.noveltheory.com Work: www.njtheater.com
    Blog: www.honestillusion.com Day Job: www.partsearch.com

    "Mark" <Mark@nowhere.c om> wrote in message
    news:uQz4Cf0RFH A.2348@TK2MSFTN GP09.phx.gbl...[color=blue]
    > I have an abstract class, and a set of classes that inherit from my[/color]
    abstract[color=blue]
    > class. The fact that it is abstract is likely irrelevant. I have a static
    > factory method in my abstract class that creates subclasses. The
    > constructor in my subclasses must be able to call the constructor in my[/color]
    base[color=blue]
    > class. For the factory method in my abstract class to call the[/color]
    constructor[color=blue]
    > on my subclasses, the constructor in the subclass MUST be public (or
    > internal). They cannot be private or protected. However, doen't that
    > basically defeat the purpose of factory? I'd love to be able to make all
    > these constructors private or similar so that someone can't create[/color]
    subclass[color=blue]
    > instances without using the Factory. If this was all in a separate DLL, I
    > suppose I'd be saved by "internal", but we have small team of developers
    > working on projects where that type of seperation really shouldn't be
    > necessary.
    >
    > Suggestions? Code sample below ...
    >
    > Thanks in advance.
    >
    > Mark
    >
    >
    > public abstract class MyBase
    > {
    > protected string first;
    >
    > public MyBase(string first )
    > {
    > this.first = first;
    > }
    >
    > public static MyBase Factory(int stateId)
    > {
    > switch (stateId)
    > {
    > case 700:
    > return new MySubClass1(fir st);
    > default:
    > throw new Exception("Bogu s code!");
    > }
    > }
    > }
    >
    >[/color]


    Comment

    • Ollie Riches

      #3
      Re: Factory method

      check out the definition here




      --
      HTH

      Ollie Riches


      Disclaimer: Opinions expressed in this forum are my own, and not
      representative of my employer.
      I do not answer questions on behalf of my employer. I'm just a programmer
      helping programmers.

      "Mark" <Mark@nowhere.c om> wrote in message
      news:uQz4Cf0RFH A.2348@TK2MSFTN GP09.phx.gbl...[color=blue]
      > I have an abstract class, and a set of classes that inherit from my[/color]
      abstract[color=blue]
      > class. The fact that it is abstract is likely irrelevant. I have a static
      > factory method in my abstract class that creates subclasses. The
      > constructor in my subclasses must be able to call the constructor in my[/color]
      base[color=blue]
      > class. For the factory method in my abstract class to call the[/color]
      constructor[color=blue]
      > on my subclasses, the constructor in the subclass MUST be public (or
      > internal). They cannot be private or protected. However, doen't that
      > basically defeat the purpose of factory? I'd love to be able to make all
      > these constructors private or similar so that someone can't create[/color]
      subclass[color=blue]
      > instances without using the Factory. If this was all in a separate DLL, I
      > suppose I'd be saved by "internal", but we have small team of developers
      > working on projects where that type of seperation really shouldn't be
      > necessary.
      >
      > Suggestions? Code sample below ...
      >
      > Thanks in advance.
      >
      > Mark
      >
      >
      > public abstract class MyBase
      > {
      > protected string first;
      >
      > public MyBase(string first )
      > {
      > this.first = first;
      > }
      >
      > public static MyBase Factory(int stateId)
      > {
      > switch (stateId)
      > {
      > case 700:
      > return new MySubClass1(fir st);
      > default:
      > throw new Exception("Bogu s code!");
      > }
      > }
      > }
      >
      >[/color]


      Comment

      • PIEBALD

        #4
        RE: Factory method

        I've been looking at factories today too (as a work-around for the lack of
        virtual constructors). It seems that factories work best when the class
        doesn't use a parameterized constructor, but has a virtual method to
        initialize the new instance. This creates a two-step process:

        MyClass x = new MyClass() ;
        x.Initialize ( ... ) ;

        That first line means that you still need a specialized factory for each
        class, yuck.

        Ergo, I have devised the following scheme, which has its own shortcomings...

        I defined an interface:

        public interface IConstructable
        {
        void Constructor ( params object[] Params ) ;
        }

        (It sure would be nice if an interface could specify a constructor.)

        And the following static factory method:

        public static IConstructable
        New
        (
        System.Type What
        ,
        params object[] Params
        )
        {
        IConstructable result = null ;

        if ( What.GetConstru ctors().Length > 1 )
        {
        throw ( new System.Argument Exception ( string.Format
        (
        "Type {0} contains more than the default constructor."
        ,
        What.Name
        ) ) ) ;
        }

        System.Reflecti on.ConstructorI nfo con = What.GetConstru ctor ( new
        System.Type[] {} ) ;

        if ( con == null )
        {
        throw ( new System.Argument Exception ( string.Format
        (
        "Did not find a parameterless constructor for type {0}."
        ,
        What.Name
        ) ) ) ;
        }

        if ( !con.IsPublic )
        {
        throw ( new System.Argument Exception ( string.Format
        (
        "Did not find a public parameterless constructor for type
        {0}."
        ,
        What.Name
        ) ) ) ;
        }

        result = (IConstructable ) con.Invoke ( new object[] {} ) ;

        result.Construc tor ( Params ) ;

        return ( result ) ;
        }

        Then to use it for a class:

        class A : IConstructable
        {
        private string str ;

        public virtual void
        Constructor
        (
        params object[] Params
        )
        {
        this.str = (string) Params [ 0 ] ;
        }

        public override string
        ToString
        (
        )
        {
        return ( this.str ) ;
        }
        }

        And to make an instance thereof (this is the fugly part):

        A a = (A) New ( typeof(A) , "A" ) ;

        This one factory method works with any class that implements IConstructable,
        as if 'twere a virtual constructor. But the class's Constructor method will
        need to do type checking on the parameters, yuck.

        Perhaps I can have it use a struct for the parameters, hmm...

        Note that _ideally_ the class would not define a constructor, at most it may
        define a public parameterless constructor.

        Again, this was to work-around the lack of virtual constructors, so yes, an
        uninformed user may call new on the class and mess things up, but I'm still
        working on't.

        Comment

        • Nick Malik [Microsoft]

          #5
          Re: Factory method

          Here's the Flaw
          [color=blue]
          > A a = (A) New ( typeof(A) , "A" ) ;[/color]

          You used 'new'

          The point of a factory is that the calling class NEVER uses 'new'

          Your design is not a factory. It is interesting. Clever perhaps. I don't
          expect to use it.
          But it is definitely not a factory.

          --
          --- Nick Malik [Microsoft]
          MCSD, CFPS, Certified Scrummaster


          Disclaimer: Opinions expressed in this forum are my own, and not
          representative of my employer.
          I do not answer questions on behalf of my employer. I'm just a
          programmer helping programmers.
          --
          "PIEBALD" <PIEBALD@discus sions.microsoft .com> wrote in message
          news:1D782949-AAFD-467D-8832-26C4592E1583@mi crosoft.com...[color=blue]
          > I've been looking at factories today too (as a work-around for the lack of
          > virtual constructors). It seems that factories work best when the class
          > doesn't use a parameterized constructor, but has a virtual method to
          > initialize the new instance. This creates a two-step process:
          >
          > MyClass x = new MyClass() ;
          > x.Initialize ( ... ) ;
          >
          > That first line means that you still need a specialized factory for each
          > class, yuck.
          >
          > Ergo, I have devised the following scheme, which has its own
          > shortcomings...
          >
          > I defined an interface:
          >
          > public interface IConstructable
          > {
          > void Constructor ( params object[] Params ) ;
          > }
          >
          > (It sure would be nice if an interface could specify a constructor.)
          >
          > And the following static factory method:
          >
          > public static IConstructable
          > New
          > (
          > System.Type What
          > ,
          > params object[] Params
          > )
          > {
          > IConstructable result = null ;
          >
          > if ( What.GetConstru ctors().Length > 1 )
          > {
          > throw ( new System.Argument Exception ( string.Format
          > (
          > "Type {0} contains more than the default constructor."
          > ,
          > What.Name
          > ) ) ) ;
          > }
          >
          > System.Reflecti on.ConstructorI nfo con = What.GetConstru ctor ( new
          > System.Type[] {} ) ;
          >
          > if ( con == null )
          > {
          > throw ( new System.Argument Exception ( string.Format
          > (
          > "Did not find a parameterless constructor for type {0}."
          > ,
          > What.Name
          > ) ) ) ;
          > }
          >
          > if ( !con.IsPublic )
          > {
          > throw ( new System.Argument Exception ( string.Format
          > (
          > "Did not find a public parameterless constructor for type
          > {0}."
          > ,
          > What.Name
          > ) ) ) ;
          > }
          >
          > result = (IConstructable ) con.Invoke ( new object[] {} ) ;
          >
          > result.Construc tor ( Params ) ;
          >
          > return ( result ) ;
          > }
          >
          > Then to use it for a class:
          >
          > class A : IConstructable
          > {
          > private string str ;
          >
          > public virtual void
          > Constructor
          > (
          > params object[] Params
          > )
          > {
          > this.str = (string) Params [ 0 ] ;
          > }
          >
          > public override string
          > ToString
          > (
          > )
          > {
          > return ( this.str ) ;
          > }
          > }
          >
          > And to make an instance thereof (this is the fugly part):
          >
          > A a = (A) New ( typeof(A) , "A" ) ;
          >
          > This one factory method works with any class that implements
          > IConstructable,
          > as if 'twere a virtual constructor. But the class's Constructor method
          > will
          > need to do type checking on the parameters, yuck.
          >
          > Perhaps I can have it use a struct for the parameters, hmm...
          >
          > Note that _ideally_ the class would not define a constructor, at most it
          > may
          > define a public parameterless constructor.
          >
          > Again, this was to work-around the lack of virtual constructors, so yes,
          > an
          > uninformed user may call new on the class and mess things up, but I'm
          > still
          > working on't.[/color]


          Comment

          • Nick Malik [Microsoft]

            #6
            Re: Factory method

            The base class should not be bound to the list of possible inheriting
            children. The base class must not create the children. That defeats the
            purpose.

            The child object can have a public constructor. That doesn't mean that you
            will use it. If you don't want a public constructor, then define a Factory
            Method in the base class and, in the child classes, implement the factory
            method to return the object.

            You won't be able to "enforce" that the child object cannot have a public
            constructor. Why would you want to? But you can provide a mechanism that
            the child class must implement that returns an object that derives from the
            base type. The users of the class will always use this method, which means
            you no longer have to worry about it. If a child class shouldn't have a
            public constructor, write it so that the contstructor is private.

            The constructor in your subclasses can call the constructor in your base
            class. See this topic from Jon's site:


            To implement a factory method, in the base class define an abstract method
            that returns an object of the base type.

            <Warning -- uncompiled air code>

            public abstract myBaseWidget
            {
            private myBaseWidget(in t myParam)
            {
            }
            public abstract myBase CreateWidget();
            }

            public myChildWidget : myBaseWidget
            {
            private myChildWidget() : base(4)
            {
            // go do constructor things
            }
            public myChildWidget CreateWidget()
            {
            // this is your factory method!
            return new myChildWidget() ;
            }
            }



            --
            --- Nick Malik [Microsoft]
            MCSD, CFPS, Certified Scrummaster


            Disclaimer: Opinions expressed in this forum are my own, and not
            representative of my employer.
            I do not answer questions on behalf of my employer. I'm just a
            programmer helping programmers.
            --
            "Mark" <Mark@nowhere.c om> wrote in message
            news:uQz4Cf0RFH A.2348@TK2MSFTN GP09.phx.gbl...[color=blue]
            >I have an abstract class, and a set of classes that inherit from my
            >abstract class. The fact that it is abstract is likely irrelevant. I have
            >a static factory method in my abstract class that creates subclasses. The
            >constructor in my subclasses must be able to call the constructor in my
            >base class. For the factory method in my abstract class to call the
            >constructor on my subclasses, the constructor in the subclass MUST be
            >public (or internal). They cannot be private or protected. However,
            >doen't that basically defeat the purpose of factory? I'd love to be able to
            >make all these constructors private or similar so that someone can't create
            >subclass instances without using the Factory. If this was all in a
            >separate DLL, I suppose I'd be saved by "internal", but we have small team
            >of developers working on projects where that type of seperation really
            >shouldn't be necessary.
            >
            > Suggestions? Code sample below ...
            >
            > Thanks in advance.
            >
            > Mark
            >
            >
            > public abstract class MyBase
            > {
            > protected string first;
            >
            > public MyBase(string first )
            > {
            > this.first = first;
            > }
            >
            > public static MyBase Factory(int stateId)
            > {
            > switch (stateId)
            > {
            > case 700:
            > return new MySubClass1(fir st);
            > default:
            > throw new Exception("Bogu s code!");
            > }
            > }
            > }
            >
            >[/color]


            Comment

            • Steve Walker

              #7
              Re: Factory method

              In message <v_WdnT9FPMoV9_ ffRVn-rA@comcast.com> , "Nick Malik
              [Microsoft]" <nickmalik@hotm ail.nospam.com> writes
              [color=blue]
              >To implement a factory method, in the base class define an abstract method
              >that returns an object of the base type.
              >
              ><Warning -- uncompiled air code>
              >
              >public abstract myBaseWidget
              >{
              > private myBaseWidget(in t myParam)
              > {
              > }
              > public abstract myBase CreateWidget();
              >}
              >
              >public myChildWidget : myBaseWidget
              >{
              > private myChildWidget() : base(4)
              > {
              > // go do constructor things
              > }
              > public myChildWidget CreateWidget()
              > {
              > // this is your factory method!
              > return new myChildWidget() ;
              > }
              >}[/color]

              Hmm. How do you create an instance of myChildWidget in order to call the
              non-static CreateWidget method?

              --
              Steve Walker

              Comment

              • Nick Malik [Microsoft]

                #8
                Re: Factory method

                Some mornings... I write stuff that I am embarrassed to look at later :-}

                even 10 minutes later

                You are correct, of course. The factory method either has to be static (in
                which case, it isn't inherited) or part of another class altogether.

                (duh!)
                Sorry.

                --
                --- Nick Malik [Microsoft]
                MCSD, CFPS, Certified Scrummaster


                Disclaimer: Opinions expressed in this forum are my own, and not
                representative of my employer.
                I do not answer questions on behalf of my employer. I'm just a
                programmer helping programmers.
                --
                "Steve Walker" <steve@otolith. demon.co.uk> wrote in message
                news:fNfp54APco aCFwhQ@otolith. demon.co.uk...[color=blue]
                > In message <v_WdnT9FPMoV9_ ffRVn-rA@comcast.com> , "Nick Malik [Microsoft]"
                > <nickmalik@hotm ail.nospam.com> writes
                >[color=green]
                >>To implement a factory method, in the base class define an abstract method
                >>that returns an object of the base type.
                >>
                >><Warning -- uncompiled air code>
                >>
                >>public abstract myBaseWidget
                >>{
                >> private myBaseWidget(in t myParam)
                >> {
                >> }
                >> public abstract myBase CreateWidget();
                >>}
                >>
                >>public myChildWidget : myBaseWidget
                >>{
                >> private myChildWidget() : base(4)
                >> {
                >> // go do constructor things
                >> }
                >> public myChildWidget CreateWidget()
                >> {
                >> // this is your factory method!
                >> return new myChildWidget() ;
                >> }
                >>}[/color]
                >
                > Hmm. How do you create an instance of myChildWidget in order to call the
                > non-static CreateWidget method?
                >
                > --
                > Steve Walker[/color]


                Comment

                • Steve Walker

                  #9
                  Re: Factory method

                  In message <5sqdnXiQHrL6Af ffRVn-hQ@comcast.com> , "Nick Malik
                  [Microsoft]" <nickmalik@hotm ail.nospam.com> writes[color=blue]
                  >Some mornings... I write stuff that I am embarrassed to look at later :-}
                  >
                  >even 10 minutes later[/color]

                  :O)

                  Me too.
                  [color=blue]
                  >You are correct, of course. The factory method either has to be static (in
                  >which case, it isn't inherited) or part of another class altogether.[/color]

                  I find that where this happens always a thought-provoking decision.
                  Polymorphism is great, but at some point you have to bite the bullet and
                  decide exactly what it is you're going to create an instance of, and it
                  always seems somehow intellectually unsatisfying. I think the
                  subconscious appeal of the factory pattern is that you can encapsulate a
                  bit of code which you'd rather not see :o)

                  If you can justify taking the hit of using reflection, it's beautiful. I
                  once wrote a "generic business rules in database" type of system which
                  instantiated tree structures of rule subclasses by reflection, using
                  class names from a database. That was neat, but the logic for
                  determining which class to instantiate is seldom fits so well with that
                  approach.

                  --
                  Steve Walker

                  Comment

                  • Jon Skeet [C# MVP]

                    #10
                    Re: Factory method

                    Nick Malik [Microsoft] <nickmalik@hotm ail.nospam.com> wrote:[color=blue]
                    > Here's the Flaw
                    >[color=green]
                    > > A a = (A) New ( typeof(A) , "A" ) ;[/color]
                    >
                    > You used 'new'
                    >
                    > The point of a factory is that the calling class NEVER uses 'new'[/color]

                    And it doesn't - it uses New, which is a method. Note the difference in
                    case.
                    [color=blue]
                    > Your design is not a factory. It is interesting. Clever perhaps. I don't
                    > expect to use it.
                    > But it is definitely not a factory.[/color]

                    It's not quite the normal factory pattern, but I think it's still a
                    factory.

                    --
                    Jon Skeet - <skeet@pobox.co m>
                    Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                    If replying to the group, please do not mail me too

                    Comment

                    • PIEBALD

                      #11
                      Re: Factory method

                      .... and, in the child classes, implement the factory[color=blue]
                      > method to return the object.[/color]

                      I don't want to have to define a method in the child class that simply calls
                      the parent class' method. The traditional factory pattern solves some issues,
                      but I don't think it's designed to solve the problem of having to write
                      seemingly unnecessary repetitive code, whether that be a constructor or a
                      factory method.

                      My scheme allows the child class to _not_ have to define such methods (the
                      children will receive a the compiler-provided default constructor). Based on
                      class A in my previous message one can create:

                      class C : A
                      {
                      }

                      Which an app can instantiate with:

                      C c = (C) New ( typeof(C) , "C" ) ;

                      As you can see, there is no "needlessly duplicated code" in class C.

                      On the other hand, class B may add a new field, and therefore provides its
                      own Constructor method:

                      class B : A
                      {
                      private int num ;

                      public override void
                      Constructor
                      (
                      params object[] Params
                      )
                      {
                      base.Constructo r ( Params ) ;
                      this.num = (int) Params [ 1 ] ;
                      }

                      public override string
                      ToString
                      (
                      )
                      {
                      return ( base.ToString() + this.num.ToStri ng() ) ;
                      }
                      }

                      In conclusion...

                      If the child class does not define new fields (only new methods) it ought to
                      be able to use the parent class' constructor, inititalizer, factory,
                      whatever, and my scheme accomplishes this (although the code to instantiate
                      is ugly).

                      P.S. Over the weekend I tried to use a struct as the parameter to
                      Constructor without success, but that's a subject for a new thread.

                      Comment

                      Working...