From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,174ec7dc941a1068 X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!news2.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsfeed.arcor.de!newsspool4.arcor-online.net!news.arcor.de.POSTED!not-for-mail Date: Wed, 25 Jul 2007 23:06:43 +0200 From: Georg Bauhaus Organization: # User-Agent: Thunderbird 1.5.0.12 (Macintosh/20070509) MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Factory Pattern References: <1185387571.367570.163160@r34g2000hsd.googlegroups.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <46a7ba75$0$5695$9b4e6d93@newsspool2.arcor-online.net> NNTP-Posting-Date: 25 Jul 2007 23:02:45 CEST NNTP-Posting-Host: d240f489.newsspool2.arcor-online.net X-Trace: DXC=[?RDgl`GYFHFJ3]dH>I?oEA9EHlD;3YcB4Fo<]lROoRAgUcjd<3m<;BE9IUHbQfMejVHYPh2Q[DjIAG\`JP3@i5b`O X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:1186 Date: 2007-07-25T23:02:45+02:00 List-Id: 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;