3

After searching for some Abstract Factory examples using modern programming languages, I have some dillemas about the sensu lato of conceptual UML schema of Abstract, more specificly about the Client (Application) Class and its relationships

On wikipedia example, the Client code has relationships with the Factory and each (family of) Products:

enter image description here

On the other hand,on Refactoring Guru the Client code has an aggregation with Factory:

enter image description here

Can this last one be considered a "GOF" abstract factory too?

If so, would it be only on another way to simplify the diagram and make the use of concrete families implicit and not explicit?

1
  • 1
    I'm used to constantly telling that a shared aggregation has no defined semantics as per UML 2.5 (table on p. 110). So that applies here too.
    – user188153
    Feb 8, 2020 at 17:56

2 Answers 2

3

It's the same pattern, and the two diagrams are practically the same, it's just that some of the details of how the pattern is actually used are somewhat obscured, and this makes them look superficially different.

The dashed arrows represent a generalized dependency - meaning that one type somehow depends on the other, but it doesn't necessarily imply that it holds a direct reference to an instance (e.g., it could just be that the type appears as a parameter to, or as a return type of, a function).

Now, in the first picture, client code has no dependencies to (no knowledge of) concrete products or concrete factories - all the arrows from Client point only to the abstract interfaces. In other words, all client code is written only in terms of these abstract interfaces.

This is exactly the same situation as the one depicted in the second diagram, except that there the client takes the factory as a dependency through the constructor (but again, typed via the abstract interface). The fact that it's an aggregation is a detail (an implementation choice) that doesn't have any significance to the overall pattern - the important thing, and what makes it equivalent to the first diagram, is that (1) the type of the factory field is AbstractFactory (not any concrete factory), and (2) that the return types of the producer methods in AbstarctFactory are all abstract products. The fact that the client uses those types corresponds to the dashed arrows in the first diagram.

For example, someOperation() contains the line:

ProductA pa = factory.createProductA();  // Note that ProductA is the abstract type
// presumably, the remainder of the code then does something with pa

This means that Client (which defines someOperation()) depends on ProductA. This dependency is represented in the first diagram by the dashed line going from Client to AbstractProductA - it's just that this representation doesn't show exactly how this dependency occurs, just that it is there. In the second diagram, this dependency is implicit, and can be inferred from the other elements shown.

One thing that isn't shown on these diagrams is how is the concrete factory actually chosen. There's some third component that does this - it is often some kind of entry point, like the Main() method, or some kind of root to a module, or a root to some group of collaborating objects. I.e., it happens somewhere else, where you know which concrete products you want to use.

The concrete factories themselves depend on their corresponding concrete products, so these do not have to be configured (which concrete products are used is determined by the choice of a concrete factory). Once the selection is made, the abstract reference to the factory is handed over to the client in some way; this enables the client to remain decoupled from the concrete products.

So the missing piece may look something like this:

static public void Main(string[] args)
{
    // Any mention of anything concrete is confined to this line 
    // (and within the ConcreteFactory1 itself)
    AbstractFactory factory = new ConcreteFactory1();

    Client client = new Client(factory);
    client.SomeOperation();
}

The choice can be hardcoded, as here, or based on an entry in a config file, or done via preprocessor directives, or dynamically determined in some way, etc. The factory instance can be handed over to the client "manually", or it could be created, injected and managed by an IoC container.

3

The second diagram may represent an abstract factory. However you shall not see it as a reference diagram for this pattern:

  • According to GoF, the AF client uses the factory. It does not tell more. In your second diagram the client is associated to the factory. This allows its use (compliant to GoF) but is much stronger (so all GoF factories do not match the second diagram: a client could well use an AF provided as method parameter without any aggregation).
  • According to GoF, the client knows the abstract products and not the concrete products. This is left unspecified in your second schema: you can easily guess it, but the diagram could also allow to implement a concretely coupled client (I hope the text and code samples of your web site make this key point clear).
  • by the way, the precise semantic of the aggregate is left unspecified in the UML specs. It does therefore not bring additional information here, compared to a non-aggregated association.
2
  • Looking at the code in the note of the second diagram, there are some hints. ProductA pa = factory.createProductA() tells that the factory is a variable of some kind (perhaps an aggregation, perhaps a local variable as you hint) but also that createProductA returns a type ProductA showing at least a dependency to that abstract class (which is entirely missing in the diagram). Feb 9, 2020 at 3:03
  • @Fuhrmanator I fully agree ! That’s what I meant with “can easily guess”. I think that the benefit of the diagram would be higher if visualizing such important dependencies. Here, it visually hide it, and even reinforces the impression that client only knows about the abstract factory by hiding the small abstract products behind an impressive factory block, thus giving room to misinterpretation if the code snippets are not carefully analyzed by the reader.
    – Christophe
    Feb 9, 2020 at 9:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.