Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2015-11

Implementing Factory Method with Pascal

25 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

luciano de souza

Hello all,

I'd like to understand how to implement the Factory Method pattern in Pascal.

In my example, there are four classes:
1. TAnimal - The parent and abstract class;
2. TDog and TCat - The specialized classes;
3. TAnimalFactory - The class which creates instances of animals, having received a enumerator as a parameter.

The method "live" is common to TAnimal, Tdog and TCat. However, "bark" is found only in TDog.

In the following code, the compiler says that animal does not possesses "bark" as a method. It's right. The behaviour is implemented only in the derived class.

But, if this not works, how to implement the Factory Method in Freepascal?

		program test;
{$mode objfpc}{$H+}
uses
tsbase;
var
animal: TAnimal;
BEGIN
animal := TAnimalFactory.create(atDog);
try
animal.bark; // Here is the error. If the call were "animal.live, no
errors would be shown. The code does not fails with (animal as
TDog).bark, but it does not make sense. The factory should allow to
create the instance only with the enumerator, without casting.
finally
animal.free;
end;
END.
		unit tsbase;
{$mode objfpc}{$H+}
interface
type
TAnimal = class(TObject)
public
procedure live; virtual; abstract;
end;
TDog = class(TAnimal)
public
procedure live; override;
procedure bark;
end;
TCat = class(TAnimal)
public
procedure live; override;
end;
TAnimalType = (atDog, atCat);
TAnimalFactory = class(TObject)
public
class function create(AType: TAnimalType):TAnimal;
end;
implementation
{TDog}
procedure TDog.live;
begin
writeln('Um cachorro vive');
end;
procedure TDog.bark;
begin
writeln('Um cachorro foge');
end;
{TCat}
procedure TCat.live;
begin
writeln('Um gato vive');
end;
{TAnimalFactory}
class function TAnimalFactory.create(AType: TAnimalType):TAnimal;
begin
case AType of
atDog: result := TDog.create;
atCat: result := TCat.create;
end;
end;
end.

Well, I am studying design patterns, but I really does not understand how to solve this problem.

I thank you for any tip.

Best regards,

Luciano de Souza
luciano de souza
to Mattias Gaertner

Yes, it works. But in this case, I don't understand the sense of the pattern.

If I need to do "TAnimalFactory.create(atDog) as Tdog", perhaps, it would be better not to use a factory, doing simply "TDog.create".

I don't understand if I have implemented the pattern wrongly or if this pattern, becose of the strong typing of the language, does not make sense in Pascal.

2015-11-27 19:30 GMT-02:00, Mattias Gaertner :

Show quoted text 20 lines
One solution: var animal: TDog; BEGIN animal := TAnimalFactory.create(atDog) as TDog; try animal.bark; finally animal.free; end; END. Mattias _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Luciano de Souza
Graeme Geldenhuys
to luciano de souza: I'd like to understand how to implement the Factory Method pattern in Pascal. In my…
luciano de souza wrote
I'd like to understand how to implement the Factory Method pattern in Pascal.

See my "Simple Factory Pattern" article. I've written about many other design patterns too.

http://geldenhuys.co.uk/articles/

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Marcos Douglas
to luciano de souza: Yes, it works. But in this case, I don't understand the sense of the pattern. If I need…
luciano de souza wrote
If I need to do "TAnimalFactory.create(atDog) as Tdog", perhaps, it would be better not to use a factory, doing simply "TDog.create".

You're right, use simply TDog.Create.
Why do you have a factory to create different types of animals (classes)? Doesn't make sense. If you need a factory, you should use a factory for dogs, another for cats and so on.
Another tip: Factories resolve some problems but there is a cost. The factory will creates your instance (object) but it know only one constructor, ie, the base class constructor.
Objects should be immutable at first place, only if you have a good reason for don't use immutability. So, if they should be immutable, you have only the constructor to instantiate your object, passing arguments for it. If you have a constructor without arguments (using a base class for example), you won't pass arguments to instantiate your classe properly.
Another tip: use interfaces, not inheritance. Inheritance is evil. You always will have problems using inheritance. Instead, use small objects with few methods (2-5) to resolve just one problem. You don't need inheritance for that. Your code will be more simpler and customizable.
Decorator Pattern is more powerful than inheritance. Read about it.

Best regards,

Marcos Douglas

luciano de souza
to Marcos Douglas

Marcos,

Your answer and the excelent article of Graeme clarify the question.

If I want to change the type of the instance, better is to use generics. A factory is only a batch builder of the same objects.

Graeme, your article opened my mind. The mappings and the registers caused me a very strong impression. Thank you!
2015-11-27 21:48 GMT-02:00, Marcos Douglas :

Show quoted text 32 lines
On Fri, Nov 27, 2015 at 7:44 PM, luciano de souza wrote: > If I need to do "TAnimalFactory.create(atDog) as Tdog", perhaps, it > would be better not to use a factory, doing simply "TDog.create". You're right, use simply TDog.Create. Why do you have a factory to create different types of animals (classes)? Doesn't make sense. If you need a factory, you should use a factory for dogs, another for cats and so on. Another tip: Factories resolve some problems but there is a cost. The factory will creates your instance (object) but it know only one constructor, ie, the base class constructor. Objects should be immutable at first place, only if you have a good reason for don't use immutability. So, if they should be immutable, you have only the constructor to instantiate your object, passing arguments for it. If you have a constructor without arguments (using a base class for example), you won't pass arguments to instantiate your classe properly. Another tip: use interfaces, not inheritance. Inheritance is evil. You always will have problems using inheritance. Instead, use small objects with few methods (2-5) to resolve just one problem. You don't need inheritance for that. Your code will be more simpler and customizable. Decorator Pattern is more powerful than inheritance. Read about it. Best regards, Marcos Douglas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Luciano de Souza
Graeme Geldenhuys
to Anthony Walter: type IBarkable = interface(IInterface) ['{B241068F-2ED9-43C7-066B-778B94CB58F9}']…

Hi Anthony,

Anthony Walter wrote 6 lines
type IBarkable = interface(IInterface) ['{B241068F-2ED9-43C7-066B-778B94CB58F9}'] procedure Bark; end; ...snip...

That is a much better solution for what Luciano wants to accomplish.

and later ... if Animal is IBarkable then (Animal as IBarkable).Bark;

This is not good usage of Interfaces. Use the interface variable instead.

var
  intf: IBarkable
begin
  if Supports(Animal, IBarbable, intf) then
  begin
    intf.Bark;
    // you can continue here using intf further without casting
  end;

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Graeme Geldenhuys
to Marcos Douglas: You're right, use simply TDog.Create. Why do you have a factory to create different types…

Hi Marcos,

Marcos Douglas wrote
Why do you have a factory to create different types of animals (classes)? Doesn't make sense.

Maybe in Luciano's simple example a factory is not the best use case, but the Simple Factory design pattern can be very useful in other cases.

eg: tiOPF uses the Simple Factory extensively in many areas. eg: encryption. tiOPF defines a base class with abstract methods for using encryption. We then have various descendant classes that implement different encryption. Each of the descendants register themselves with the factory (tiOPF likes to use the uses clause and Initialization section for this). In your own code you then request an encryption type and get a instance object back. You use that instance via the API (interface) defined by the abstract methods.

Objects should be immutable at first place, only if you have a good reason for don't use immutability. So, if they should be immutable,

This has nothing to do with Luciano's problem.

Another tip: use interfaces, not inheritance. Inheritance is evil.

Indeed, Interfaces might be a more elegant solution to Luciano's problem
- for what he wants to achieve. Inheritance is NOT evil. It's not that black and white. Both Interfaces and Inheritance have their pros and cons - you just need to study your problem and then decide which is the better fit.

@Luciano,
What you described is the Simple Factory design pattern. I suggest you also study the Factory Method design pattern, to see the difference and where you can use them.

Two [I have many more suggestions too] Design Pattern books I highly recommend are:

* Design Patterns - Elements Of Reusable Object Oriented Software. Also known as the GoF (Gang of Four) book.

* Head First - Design Patterns
This one has a very different writing style, but I found this fun take on design patterns works very well.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Marcos Douglas
to Graeme Geldenhuys
Graeme Geldenhuys wrote
Maybe in Luciano's simple example a factory is not the best use case, but the Simple Factory design pattern can be very useful in other cases.

I agree in both affirmations. But as I said before, Factories resolve some problems but there is a cost.

Thank for explanation about tiOPF.

> Objects should be immutable at first place, only if you have a good > reason for don't use immutability. So, if they should be immutable, This has nothing to do with Luciano's problem.

I know. He is my friend a long time and so I wrote more information, just that.

Regars,

Marcos Douglas

Juha Manninen
to Marcos Douglas: You're right, use simply TDog.Create. Why do you have a factory to create different types…
Marcos Douglas wrote
Another tip: Factories resolve some problems but there is a cost. The factory will creates your instance (object) but it know only one constructor, ie, the base class constructor.

No, the constructor must then be virtual.
Inheritance is OK if all public virtual methods can be defined in an abstract base class. If works as an interface then (without "interface" keyword).
It does not work when you need TDog.Bark but it would work with abstract function TAnimal.Says: String, which is implemented as " Return 'wuff' " for TDoc and " Return 'miou' " for TCat.

But yes, the other answers are better for more complex cases.

Juha

Marcos Douglas
to Juha Manninen
Juha Manninen wrote 6 lines
On Sat, Nov 28, 2015 at 1:48 AM, Marcos Douglas wrote: > Another tip: Factories resolve some problems but there is a cost. The > factory will creates your instance (object) but it know only one > constructor, ie, the base class constructor. No, the constructor must then be virtual.

Even using virtual constructors, the factory will know only one signature to instantiate objects.
AFAIK you only will know constructor or methods arguments, in runtime, using RTTI, if you put the constructor/method as published. But, even if you put it as published, you do not know the right context to call the right constructor -- considering you have many constructors with different arguments, of course.

Inheritance is OK if all public virtual methods can be defined in an abstract base class. If works as an interface then (without "interface" keyword).

Inheritance breaks encapsulation. This was written even in GoF Patterns. There are many post, on the web, explaining why inheritance is evil. I searched on Google right now:
http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/ http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html

It does not work when you need TDog.Bark but it would work with abstract function TAnimal.Says: String, which is implemented as " Return 'wuff' " for TDoc and " Return 'miou' " for TCat.

Completing things is the source of complexity, ie, completing (abstract or virtual) methods. To complete methods in a sub class, you need to know how super class works and this violate the (first tier of) encapsulation.

Best regards,
Marcos Douglas

PS: Perhaps this video could be interesting
http://www.infoq.com/presentations/Simple-Made-Easy

Serguei TARASSOV

Hello,

What is an explanation why the first code is not good but the second one is good?
At least, the first code is three times as shorter and clear. Second code seems to be taken from Delphi 7 where the first one doesn't works.

Show quoted text 11 lines
> >if Animal is IBarkable then (Animal as IBarkable).Bark; This is not good usage of Interfaces. Use the interface variable instead. var intf: IBarkable begin if Supports(Animal, IBarbable, intf) then begin intf.Bark; // you can continue here using intf further without casting end;
Regards, Serguei
Juha Manninen
to Marcos Douglas: On Sat, Nov 28, 2015 at 9:11 AM, Juha Manninen Even using virtual constructors, the…
Marcos Douglas wrote
Even using virtual constructors, the factory will know only one signature to instantiate objects.

Yes and often that is enough.
A constructor is then part of the API. (Lets call it API now to avoid confusion with the "interface" keyword.)

Completing things is the source of complexity, ie, completing (abstract or virtual) methods. To complete methods in a sub class, you need to know how super class works and this violate the (first tier of) encapsulation.

Yes, if the super class does something useful by itself, then often your class design is wrong.
My example was about an abstact base class that only provides an API, the derived classes implement it. The concept is similar to an interface definition, but often the implementation is more compact and easier to read.
Interface can define only methods. An abstract base class can have also variables and protected helper methods needed by the implementation code.

We are partly talking about different things here. You and the articly you linked advocate the "composition over inheritance" principle. Yes, it is a good principle. I also advocate it, but I also say that using abstract base classes for APIs is often a cleaner and easier way compared to interface types.
Look at the Lazarus API defined in IDEIntf package. It uses abstract base classes and works well.

Abstract base classes do not work in a multiple inheritance case. Then an interface type must be used.
However it is very rarely needed when the "composition over inheritance" principle is followed.

Juha

Marco van de Voort
to Marcos Douglas: On Sat, Nov 28, 2015 at 9:11 AM, Juha Manninen Even using virtual constructors, the…

In our previous episode, Marcos Douglas said:

Show quoted text 6 lines
Inheritance breaks encapsulation. This was written even in GoF Patterns. There are many post, on the web, explaining why inheritance is evil. I searched on Google right now: http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/ http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html

Such rants are in direct opposition of GoF. GoF never meant to push a set of unbendable rules. They just wanted to standarize jargon, and describe somethings they encountered (without any claim that everybody should use it).

Aside from the fact that interfaces is still inheritance.

Michael Van Canneyt
to Marcos Douglas: On Sat, Nov 28, 2015 at 9:11 AM, Juha Manninen Even using virtual constructors, the…
Marcos Douglas wrote 6 lines
Inheritance breaks encapsulation. This was written even in GoF Patterns. There are many post, on the web, explaining why inheritance is evil. I searched on Google right now: http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/ http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html

A perfect example why 90% of internet (and in particular blogs) are a waste of bandwidth.

From the silly-example-department: (a close cousin of the "ministry of silly walks")

A dog *is* an animal, a dog does not *have* an animal.

However (and now it gets tricky):
A human can have an animal (e.g. a dog), but she *is* also an animal.

On top of that, (s)he can inherit things from his ancestors. (for example AIDS or some other nasty disease. Or several millions of dollars)

!! OMG !! Maybe we just discovered a new form of multiple inheritance... Definite proof we should all use C++, or maybe it is time for C+++ !!

Please...

There is no golden rule which encapsulates (sic) all situations.

People should use their brain and choose a pattern or methodology judiciously, instead of wasting other people's time with stupid rants on blogs.

Michael.

Marcos Douglas
to Marco van de Voort: In our previous episode, Marcos Douglas said: Such rants are in direct opposition of GoF.…
Marco van de Voort wrote 12 lines
In our previous episode, Marcos Douglas said: > > Inheritance breaks encapsulation. This was written even in GoF Patterns. > There are many post, on the web, explaining why inheritance is evil. > I searched on Google right now: > http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/ > http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html Such rants are in direct opposition of GoF. GoF never meant to push a set of unbendable rules. They just wanted to standarize jargon, and describe somethings they encountered (without any claim that everybody should use it).

I only chose two links to put into the email. There are many other ... I just pointed some examples because they have examples.

In my GoF book (Portuguese version), page 34, says: ...It is often said that "inheritance violates encapsulation"... [free translation]

Page 35:
"Preferably the object composition instead of class inheritance." [free translation]

Aside from the fact that interfaces is still inheritance.

This is different. There is no behavior, only a contract.

Marcos Douglas
to Michael Van Canneyt: A perfect example why 90% of internet (and in particular blogs) are a waste of bandwidth.…
Michael Van Canneyt wrote
!! OMG !! Maybe we just discovered a new form of multiple inheritance... Definite proof we should all use C++, or maybe it is time for C+++ !!

You have humor, very funny. [clap clap clap]

Please... There is no golden rule which encapsulates (sic) all situations.

I agree with you.

People should use their brain and choose a pattern or methodology judiciously, instead of wasting other people's time with stupid rants on blogs.

As I said before, I put some links just because they have examples to simplify what I was saying.
If you would like, I can search some links "less stupid" for you. Some people, more important and influent than me, should have written about it too... maybe?

Now, please...
Tell us yours arguments. Explain why I'm wrong (and many others on the web). Inheritance is good... why?
Inheritance is better than composition... why?
What problems we have using composition or inheritance? Which is better or simpler to use?

If I'm wrong and you, using valid arguments, explain to me where are my mistakes, I will thank you for teaching me some new for me. But if you have only jokes please don't waste my time to read and answer you.

Best regards,
Marcos Douglas

PS: I don't want a fight. We owe a lot to you with your work in the FPC. I respect you as a programmer, as FPC Team member, as professional.

Michael Van Canneyt
to Marcos Douglas: On Sat, Nov 28, 2015 at 5:34 PM, Michael Van Canneyt You have humor, very funny. [clap…
Marcos Douglas wrote 23 lines
On Sat, Nov 28, 2015 at 5:34 PM, Michael Van Canneyt wrote: > > !! OMG !! Maybe we just discovered a new form of multiple inheritance... > Definite proof we should all use C++, or maybe it is time for C+++ !! You have humor, very funny. [clap clap clap] > Please... > > There is no golden rule which encapsulates (sic) all situations. I agree with you. > People should use their brain and choose a pattern or methodology > judiciously, instead of wasting other people's time with stupid rants on > blogs. As I said before, I put some links just because they have examples to simplify what I was saying. If you would like, I can search some links "less stupid" for you. Some people, more important and influent than me, should have written about it too... maybe?

Don't bother.

Now, please... Tell us yours arguments. Explain why I'm wrong (and many others on the web).

I did not say you were wrong ? Where did you read that ?

Inheritance is good... why? Inheritance is better than composition... why?

I did not say that inheritance is good, and I did not say that inheritance is better than composition.

Where did you read that ?

They are simply different techniques, and you must choose the one appropriate for the situation you have.

First of all, inheritance is inherent in object oriented programming, since every object descends from a base object. So saying that 'inheritance must die' is a stupid sentence or title for a blog.

You can read the following everywhere:
Inheritance describes a relation between objects of the type 'is a' Composition describes a relation between objects of the type 'has a'

When you construct your object tree (if you want a tree) you must choose your objects and relations in the best possible way.

What problems we have using composition or inheritance? Which is better or simpler to use?

The point I am trying to make is that these are wrong questions to begin with.

Sometimes inheritance is "better", sometimes composition is "better". The answer depends on the situation.

The good engineer will probably make more appropriate choices than the bad engineer. An engineer that says 'I will always use inheritance' is rigid, and so is the engineer that says 'I will always use composition'.

The good engineer chooses the right tool for the job. The good engineer will understand better when he has to use 'is a' and when to use 'has a'.

You can have a hammer and a saw. They are different tools. Depending on the situation you will use the hammer or the saw. No carpenter will say that the hammer is better than the saw. Or the saw is better than the hammer.

The exact same is true for inheritance and composition.

That said, there are some objective minuses to composition:

- Longer typing. Composition:

MyObject.MyHasABehaviour.DoSomething

Inheritance:

MyObject.DoSomething

- Composition results in slower code (1), since the program must always dereference and fetch an extra object.

- Composition results in more memory being used. Inheritance puts everything in 1 block: parent+child. Composition uses 2 blocks, plus a pointer to connect the two. Every memory block introces an extra area. If you have a really bad designed hierarchy, then the 'child' object needs an extra pointer to the 'parent'. Again extra memory.

- Composition results in slower code (2) because the extra memory blocks must be managed.

You can argue that this is irrelevant these days: well, it is relevant, because the effect of this is exponential, not linear.

Not a technical argument, but nevertheless: If you think about it, composition is just some syntactic sugar for procedural programming, just as they do in C.

If I'm wrong and you, using valid arguments, explain to me where are my mistakes, I will thank you for teaching me some new for me. But if you have only jokes please don't waste my time to read and answer you.

I thought it was obvious that my joke was aimed at the authors of the web pages you posted, likely, they were frustrated by having to use wrongly designed classes.

If I have offended you, I apologize for that, this surely was not my intention.

Michael.

Marcos Douglas
to Michael Van Canneyt
Michael Van Canneyt wrote
> First of all, inheritance is inherent in object oriented programming,

since

every object descends from a base object. So saying that 'inheritance must die' is a stupid sentence or title for a blog.

Now I see what's happened.
My laziness made me just point to two links, because I did not want to write a complete example. I should have said before: 1- Inheritance is evil, be careful, use it wisely -- fast food is evil too, but I eat (sometimes) anyway.
2- I prefer composition instead inheritance because it's more simpler to use and understand.
And the most important (for me):
3- Composition is not about only 'has a' construction, but more about Decorator design pattern.

IMHO Decorators are more flexible to add features than use sublcasses.

- Composition results in slower code (1), since the program must always dereference and fetch an extra object. - Composition results in more memory being used. Inheritance puts

everything

Show quoted text 9 lines
in 1 block: parent+child. Composition uses 2 blocks, plus a pointer to connect the two. Every memory block introces an extra area. If you have a really bad designed hierarchy, then the 'child' object needs an extra pointer to the 'parent'. Again extra memory. - Composition results in slower code (2) because the extra memory blocks must be managed.

Performance and memory, of course.
Well, my priorities are design, simplicity and manutenability. I think we're both right, just depends of contexts and priorities.

You can argue that this is irrelevant these days: well, it is relevant, because the effect of this is exponential, not linear.

Yeah, I think like that in most cases, but you're right when says this is exponential problem. Not all problems can be solved with pure object orientation, of course, and that is the reason we have hammer and saw.

Not a technical argument, but nevertheless: If you think about it, composition is just some syntactic sugar for procedural programming, just

as

they do in C.

I don't understand why do you think this.

I thought it was obvious that my joke was aimed at the authors of the web pages you posted, not at you. Most likely, they were frustrated by having to use wrongly designed

classes.

As I said above, I should had written my examples or have explained more my thoughts, but I didn't. My fault. Nevertheless you wrote for me, so I think the joke wasn't just for the links but for the general context, ie, what I said plus links.

If I have offended you, I apologize for that, this surely was not my intention.

I appreciate that. No problem. Let's put a rock in this debate and move on. Thanks.

Marcos Douglas