comp.lang.ada
 help / color / mirror / Atom feed
From: Georg Bauhaus <bauhaus.rm.tsoh@maps.futureapps.de>
Subject: Re: Factory Pattern
Date: Wed, 25 Jul 2007 23:06:43 +0200
Date: 2007-07-25T23:02:45+02:00	[thread overview]
Message-ID: <46a7ba75$0$5695$9b4e6d93@newsspool2.arcor-online.net> (raw)
In-Reply-To: <ehg8y50sqs84$.2grfhftszzrg$.dlg@40tude.net>

Dmitry A. Kazakov wrote:
> On Wed, 25 Jul 2007 11:19:31 -0700, shaunpatterson@gmail.com wrote:

>> function create (i : Integer) return MessageInteger is
>>      msg : MessageInteger;
>> begin
>>      msg.value := i;
>>      return msg;
> 
> You could use an extension aggregate here:
> 
>    return (Message with I);

Or even

     return (Message with value => I);


>> Factory method:
>>
>> -- I would like it to work like this...
>> function createMessage (type : Integer) return Message_Class is
> 
> "Type" is a reserved word.
> 
>> begin
>>          case type is
>>                  when 0 =>
>>                       return MessageInteger_Pkg.create (1234);
>>                  when others =>
>>                        return MessageSomethingElse_Pkg.create
>> ("blah");
>>          end case
>>
>> end createMessage
> 
>   function Factory (What : Integer) return Message'Class is

Let me just stress that 'Class is the important part of Factory 
because it adds the polymophism: T'Class stands for all types that
have T as a parent (including T). This roughly corresponds to the
pointer use in C++ but as Dmitry has already mentioned, the Ada
language takes care of polymorphic reference for you already for
'Class types. (And it isn't pointing that adds polymorphism, it
is 'Class.)
So you needn't return pointers to objects in the T hierarchy.
You can just return objects.

  The returned objects will either be passed to subprograms,
or assigned. 


   Some_Message_Op(Factory(Event));
     -- chosen based on what Factory returns (the return
     -- value's tag)


   declare
      What_is_It: Message'Class := Factory (Event);
   begin
      Some_Message_Op(What_is_It);
        -- chosen based on tag of What_Is_It
      ...
   end;


   declare
      What_is_It: MessageInteger := MessageInteger(Factory (Event));
       -- you could do this if you know that the Factory returns an 
       -- object that can act as one of type MessageInteger
   begin
      if What_is_It.value > 42 then
        ...
   end;


>    begin
>       case What is
>          when 0 => return MessageInteger_Pkg.Create (1234);
>          ...

Another feature that I would consider when writing a factory is
case coverage, like this:
 As your program is such that you know all *possible* types
before runtime, define an enumeration that has an identifier
for each of the possible types.  Then in the body of Facroty,
leave out "others" from the case statement. The compiler will
then check that all cases are covered which makes the factory
more predictable.

This works for user defined numeric types, too. For example,
if the What variable stands for expected average number
of births per woman in one socioeconometeriological region,
the Factory will create family types:

   type Kid_Count is range 0 .. 20;

   What := Births_per_Woman
      (Latitude => ..., GDP => ..., Wheather => ...);

   case What is

      when 0 =>
         return Couples.Create;

      when 1 =>
         if Longitude in China.West .. China.East then
            return China.Create(1);
         else
            return High_Tec.Create(Average => 1.27);
         end if;

      when 2 =>
         return Saturated.Create(1.73);

      when 3 | 4 => 
         return Sunnier.Create(Population => Mixed);

      when 5 =>
          return Silent_Africa.Create(...);

      when 6 .. 8 =>
         return Shaken_Africa.Create(...);

      when 9 .. 20 =>
          return Random.Create;
   end case;




  reply	other threads:[~2007-07-25 21:06 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-25 18:19 Factory Pattern shaunpatterson
2007-07-25 18:28 ` Martin
2007-07-25 18:51 ` Dmitry A. Kazakov
2007-07-25 21:06   ` Georg Bauhaus [this message]
2007-07-25 19:27 ` Matthew Heaney
2007-07-26  0:51 ` Jeffrey R. Carter
2007-07-26  6:44   ` Maciej Sobczak
2007-07-26  8:40     ` Georg Bauhaus
2007-07-26  9:53       ` Dmitry A. Kazakov
2007-07-26 11:01         ` Georg Bauhaus
2007-07-26 13:02           ` Maciej Sobczak
2007-07-26 13:44             ` Dmitry A. Kazakov
2007-07-26 14:58             ` Georg Bauhaus
2007-07-26 22:31             ` Randy Brukardt
2007-07-27 13:07               ` Maciej Sobczak
2007-07-27 14:23                 ` shaunpatterson
2007-07-27 22:23                 ` Randy Brukardt
2007-07-28 18:56                   ` Maciej Sobczak
2007-07-29  7:54                   ` Maciej Sobczak
2007-07-29  8:53                     ` Dmitry A. Kazakov
2007-07-29 10:53                     ` Georg Bauhaus
2007-07-26 16:58         ` Adam Beneschan
2007-07-29 11:38         ` Manuel Gomez
2007-07-27 10:16     ` Jeffrey R. Carter
2007-07-27 12:47       ` Maciej Sobczak
2007-08-26  7:18         ` David Thompson
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox