inetbot web crawler
Main  |  Get access to the repository  |  API  |  The robot  |  Publications  |  Usenet Groups  |  Plainweb  | 
 inetbot - Groups (beta)

Current group: comp.object.

Which pattern does this conform to?

Which pattern does this conform to?  
Jimmy Cerra
 Re: Which pattern does this conform to?  
Andrew McDonagh
 Re: Which pattern does this conform to?  
Jimmy Cerra
 Re: Which pattern does this conform to?  
iamfractal at hotmail.com
 Re: Which pattern does this conform to?  
Daniel T.
From:Jimmy Cerra
Subject:Which pattern does this conform to?
Date:Mon, 17 Jan 2005 20:01:20 GMT
Hi. I've been struggling lately while designing a framework [1, 2], so
I examined some existing solutions. I noticed a bunch of frameworks
organized in the following fashion, so I'm wondering if it is a specific
pattern.

The problem is that using an abstract factory to build families of
related objects is awkward when those objects depend on their own
family's types rather than their base types. This could violate the
Liskov Substitution Principle [1]. For instance, consider the abstract
toolkit:

] package AbstractWidgets;
] interface AbstractFactory {
] Window getWindow();
] Button getButton();
] ...
] }
] interface Window {
] void add(Button bb);
] ...
] }
] interface Button {...}

Two different implementations may not have compatible look-and-feels
(i.e. Motif vs. WindowsXP based) or depend on incompatible drawing
libraries (i.e. GTK vs. QT based). However, a client could still
associate these two implementations:

] Window ww = aGtkBasedToolkit.getWindow();
] Button bb = aQtBasedToolkit.getButton();
] ww.add(bb);

That's not good. It seems to be especially hard to prevent these kinds
of mistakes in languages without built-in templates or generics.

The problem seems to have been avoided in some frameworks by making the
dependent objects responsible for creating their dependencies:

] package AbstractWidgets;
] interface AbstractFactory {
] Window getWindow();
] ...
] }
] interface Window {
] Button createButton();
] ...
] }
] interface Button {...}

Now the implementations are free to define their own quirks without
violating the LSP:

] package GtkWidgets;
] import AbstractWidgets.*;
] class GtkBasedToolkit implements AbstractFactory {
] Window getWindow() {
] return new GtkWindow;
] }
] ...
] }
] class GtkWindow implements Window {
] private static GtkLib gg = new GtkLib();
] Button createButton() {
] return new GtkButton(gg);
] }
] ...
] }
] class GtkButton implements Button {
] protected Button(GtkLib gg) {...}
] ...
] }

Clients then use them like this:

] Window ww = aGtkBasedToolkit.getWindow();
] Button bb = ww.createButton();

Disadvantages (that I can see) of this design include:

* It is hard to change the framework to support new Objects.

* It may violate the single responsibility principle, since classes are
responsible for their behavior and creating other objects.

One example of the pattern is the Document Object in the W3C's DOM. You
create it's components with the instance rather than the Builder that
creates the Document Object:

] Document dd = aDocumentBuilder.parse(file);
] Element ee = dd.createElement(tagName);
] // use ee

Another example is in JDBC. To create a statement to query a databse,
one uses a Connection rather than a DriverManager object:

] Connection cc = DriverManager.getConnection(urlString);
] Statement ss = cc.createStatement();
] ResultSet rr = ss.executeQuery(sqlString);

Is there a name for this pattern? Am I misinterpreting a classic
pattern in these cases?

--
Jimmy Cerra
https://nemo.dev.java.net

[1] http://groups-beta.google.com/group/comp.object/
browse_frm/thread/cf00bdcc47966776/e7685d427e30a5f1

[2] http://groups-beta.google.com/group/comp.object/
browse_frm/thread/aec14c5f186e804e/e5032a71e0cce334
From:Andrew McDonagh
Subject:Re: Which pattern does this conform to?
Date:Mon, 17 Jan 2005 23:09:10 +0000
Jimmy Cerra wrote:
> Hi. I've been struggling lately while designing a framework [1, 2], so
> I examined some existing solutions. I noticed a bunch of frameworks
> organized in the following fashion, so I'm wondering if it is a specific
> pattern.
>
> The problem is that using an abstract factory to build families of
> related objects is awkward when those objects depend on their own
> family's types rather than their base types. This could violate the
> Liskov Substitution Principle [1]. For instance, consider the abstract
> toolkit:
>
> ] package AbstractWidgets;
> ] interface AbstractFactory {
> ] Window getWindow();
> ] Button getButton();
> ] ...
> ] }
> ] interface Window {
> ] void add(Button bb);
> ] ...
> ] }
> ] interface Button {...}
>
> Two different implementations may not have compatible look-and-feels
> (i.e. Motif vs. WindowsXP based) or depend on incompatible drawing
> libraries (i.e. GTK vs. QT based). However, a client could still
> associate these two implementations:
>
> ] Window ww = aGtkBasedToolkit.getWindow();
> ] Button bb = aQtBasedToolkit.getButton();
> ] ww.add(bb);
>
> That's not good. It seems to be especially hard to prevent these kinds
> of mistakes in languages without built-in templates or generics.


I think this is the cause of your confusion. Typically you wouldn't
have access to the actual concrete factory in your application. There
would only be access to the AbstractFactory which is initialised with
the appropriate Concrete factory. Therefore you would not be able to
have this invalid association.

The client code gets the concrete factory (via an interface) from the
Abstractfactory. From the Concrete factory it would call the generic
createBlarBlar methods. But the client code does not know what actual
concrete factory it is using.

public class WindowingAbstractFactory {

public static WindowFactory getFactory() {
return m_concreteFactory;
}

private WindowingAbstractFactory() {
// Load appropriate Concrete factory depending upon platform
// if (MSwindows)
// m_concreteFactory = new MsWindowsConcreteFactory
// else if (Mac)
// m_concreteFactory = new MacConcreteFactory
// ...

}

private static WindowFactory m_concreteFactory;
}



public interface WindowFactory {

Frame createFrame();
Button createButton();

}


public class MsWindowsFactory implements WindowFactory {

public Frame createFrame() {
//create an appropriate MS Windows frame
}

public Button createButton() {
...
}

}


public class GtkWindowFactory implements WindowFactory {

public Frame createFrame() {
// create the appropriate GTK window
}

public Button createButton() {
...
}

}
From:Jimmy Cerra
Subject:Re: Which pattern does this conform to?
Date:Tue, 18 Jan 2005 04:48:48 GMT
Andrew McDonagh wrote:
> I think this is the cause of your confusion. Typically you wouldn't
> have access to the actual concrete factory in your application. There
> would only be access to the AbstractFactory which is initialised with
> the appropriate Concrete factory. Therefore you would not be able to
> have this invalid association.
>
> The client code gets the concrete factory (via an interface) from the
> Abstractfactory. From the Concrete factory it would call the generic
> createBlarBlar methods. But the client code does not know what actual
> concrete factory it is using.

Many Abstract Factories use that way to choose a particular
implementation. I believe that both java.sql.DriverManager and
javax.xml.parsers.DocumentBuilderFactory both use that idiom, for
example. And it is a good design.

However, it isn't appropriate for all cases. The example in GoF uses a
different idiom, and a design that I'm considering uses factory methods
to select the appropriate AF. I also dislike static factories from a
stylistic POV; often they are more trouble than they're worth.

P.S. I don't think anyone in my earlier thread [1] raised that
particular objection to the design. The comments generally were one of:

1. It violated the LSP, so change the object's responsibilities.
2. It violated the LSP, but that's OK.
3. It didn't violate it and wasn't a design flaw.
4. It didn't violate it and wasn't a design flaw, but a usage flaw (?).

I took (1) to heart while considering (2)-(4), and recognized this
pattern. It is still entirely possible that I'm mistaken. Could you
elaborate on these points?

--
Jimmy Cerra

[1] http://groups-beta.google.com/group/comp.object/
browse_frm/thread/cf00bdcc47966776/e7685d427e30a5f1
From:iamfractal at hotmail.com
Subject:Re: Which pattern does this conform to?
Date:18 Jan 2005 01:52:23 -0800

Andrew McDonagh wrote:
> Jimmy Cerra wrote:
> > Hi. I've been struggling lately while designing a framework [1,
2], so
> > I examined some existing solutions. I noticed a bunch of
frameworks
> > organized in the following fashion, so I'm wondering if it is a
specific
> > pattern.
> >
> >

[Herr Snipski]

Hi, folks!

I agree with Andrew that you usually don't have direct access to the
concrete factory class; but I usually do allow the user to switch
implementations behind the factory's interface. I usually use a
parameterized factory method for this, so the user can do the
following (if he wishes):

Factory gtkFactory = options.getFactory(Options.GTK_FACTORY);
Factory qtFactory = options.getFactory(Options.QT_FACTORY);

So at least in my applications, the user can play havok by passing
GTK-implementations to QT-implementations.


> > That's not good. It seems to be especially hard to prevent these
kinds
> > of mistakes in languages without built-in templates or generics.
>
>

Engineering is compromise. It's of course, "Not good," if the user
mixes implemenations and causes a program to crash. But the abstract
factory pattern offers the advantage that, if the user is careful, he
can have identical application code working with different toolkit
implementations.

This, of course, you're fully aware of; I just wanted to point out
that it would be rash to dump the abstract factory pattern on the
grounds of any one disadvantage. Not that the OP proposed dumping it,
of course.

Getting back to that, "It seems to be especially hard to prevent these
kinds of mistakes ..." It's especially hard to prevent the user making
all sorts of mistakes. Some of them do it for a living, poor things.

I would say that the answer is good ol' documentation. Tell your users
not to mix impelmentations. They'll still do it, but not for very
long; and you'll be able to say, "Told ya so." The benefit of uniform
access to the different implementations outweighs the cost potential
crashes. If you want type-safe prevention of such crashes, then drop
the abstract factory pattern and, "Program to an implementation, not
an interface." (Ouch.)

Furthermore, the OP asks, "Is there a name for this pattern? Am I
misinterpreting a classic pattern in these cases?"

I don't see a strong pattern in the Window creating the Button, rather
than the factory creating Window and Button itself. Perhaps mild
delegation.

I don't think you're misinterpreting a classic pattern; perhaps you
thought that all design patterns were perfect or flawless: they are
not; they are engineering solutions whose benefits and costs must be
weighed per-application, and whose limitations should not be
overlooked.

Not long now to Episode III. I'd bet Darth wouldn't tolerate users
mixing implementations. "Apologies accepted, user Nieder."
..ed

www.EdmundKirwan.com - Home of The Fractal Class Composition.
From:Daniel T.
Subject:Re: Which pattern does this conform to?
Date:Wed, 19 Jan 2005 12:32:42 GMT
Jimmy Cerra wrote:

> Hi. I've been struggling lately while designing a framework [1, 2], so
> I examined some existing solutions. I noticed a bunch of frameworks
> organized in the following fashion, so I'm wondering if it is a specific
> pattern.
>
> The problem is that using an abstract factory to build families of
> related objects is awkward when those objects depend on their own
> family's types rather than their base types. This could violate the
> Liskov Substitution Principle [1]. For instance, consider the abstract
> toolkit:
>
> ] package AbstractWidgets;
> ] interface AbstractFactory {
> ] Window getWindow();
> ] Button getButton();
> ] ...
> ] }
> ] interface Window {
> ] void add(Button bb);
> ] ...
> ] }
> ] interface Button {...}
>
> Two different implementations may not have compatible look-and-feels
> (i.e. Motif vs. WindowsXP based) or depend on incompatible drawing
> libraries (i.e. GTK vs. QT based). However, a client could still
> associate these two implementations:
>
> ] Window ww = aGtkBasedToolkit.getWindow();
> ] Button bb = aQtBasedToolkit.getButton();
> ] ww.add(bb);
>
> That's not good. It seems to be especially hard to prevent these kinds
> of mistakes in languages without built-in templates or generics.
>
> The problem seems to have been avoided in some frameworks by making the
> dependent objects responsible for creating their dependencies:
>
> ] package AbstractWidgets;
> ] interface AbstractFactory {
> ] Window getWindow();
> ] ...
> ] }
> ] interface Window {
> ] Button createButton();
> ] ...
> ] }
> ] interface Button {...}
>
> Now the implementations are free to define their own quirks without
> violating the LSP:
>
> ] package GtkWidgets;
> ] import AbstractWidgets.*;
> ] class GtkBasedToolkit implements AbstractFactory {
> ] Window getWindow() {
> ] return new GtkWindow;
> ] }
> ] ...
> ] }
> ] class GtkWindow implements Window {
> ] private static GtkLib gg = new GtkLib();
> ] Button createButton() {
> ] return new GtkButton(gg);
> ] }
> ] ...
> ] }
> ] class GtkButton implements Button {
> ] protected Button(GtkLib gg) {...}
> ] ...
> ] }
>
> Clients then use them like this:
>
> ] Window ww = aGtkBasedToolkit.getWindow();
> ] Button bb = ww.createButton();
>
> Disadvantages (that I can see) of this design include:
>
> * It is hard to change the framework to support new Objects.
>
> * It may violate the single responsibility principle, since classes are
> responsible for their behavior and creating other objects.
>
> One example of the pattern is the Document Object in the W3C's DOM. You
> create it's components with the instance rather than the Builder that
> creates the Document Object:
>
> ] Document dd = aDocumentBuilder.parse(file);
> ] Element ee = dd.createElement(tagName);
> ] // use ee
>
> Another example is in JDBC. To create a statement to query a databse,
> one uses a Connection rather than a DriverManager object:
>
> ] Connection cc = DriverManager.getConnection(urlString);
> ] Statement ss = cc.createStatement();
> ] ResultSet rr = ss.executeQuery(sqlString);
>
> Is there a name for this pattern? Am I misinterpreting a classic
> pattern in these cases?

Your problem, IMO, is that you are allowing multiple factories to exist.
Make AbstractWidgets a singleton and the clients won't be able to create
two of them at the same time.
   

Copyright © 2006 inetbot   -   All rights reserved