I have a Product class that contains methods and a complex data structure. I will have 8 types of products that differ only in the contents of the data structure, nothing else. In my application I will then need to create one instance of each of the 8 types of product, once, and the types of products that exist do not change at run-time.
What is the best approach and why?
A) Class Product has 8 sub-classes. Each of these sub-classes defines only the constructor. Inside each constructor the data structure is properly created for that type of product.
B) A Factory class has 8 sub-classes. Each of these sub-classes is a concrete factory for each of the 8 types of products. Class Product has no sub-classes. Each concrete factory creates the specific type of product by creating the appropriate data structure and passing it as an argument to the constructor of class Product.
I have been reviewing the advantages of the Factory design pattern and I can't see, for this specific case, any of those advantages in B over A. Am I missing something?
I would go with a variation of A, plus perhaps a factory class. A factory is meant to create classes with methods defined in an interface class, such that the consumer of the factory-created object doesn't know what type of object they are dealing with, but only the interface. The factory itself knows what type of object to create.
If there is a certain type of logic for what type of Product to create at a given time, implement a factory for 8 Products that implement an IProduct interface, and implement the logic for what type of product to create inside the factory.
I believe in Factory design pattern you can create objects of different subclasses from a single factory. See following example-
According to me using subclass approach with the factory design pattern would be a better option for the mentioned scenario.
You have mentioned - I will have 8 types of products that differ only in the contents of the data structure, nothing else.... That means state and methods are same with different contents. Based on that I feel this is clear indication that these are not subclasses but instances of same class. I think the code will contain only one product class and 8 instances of those. Factory is absolutely not required it will be unnecessary code.
Related
I'm currently designing the domain for a reservation system meant for 2 types of reservations.
Both of these types have common properties, such as their date and location. Both also have properties which the other does not, though. Examples here are in one type you can bring along guests, and not with the other; or you can request lunch for one type, and not the other.
Currently I have an abstract Reservation class, with a concrete implementations per type of reservation. I then have a ReservationBuilder which takes an enum (reservation type) as argument in its constructor. This builder would then contain methods for both types of reservations, and using a method for a type of reservation that cannot use the information would either do nothing when built, or throw an error.
Something tells me that this isn't a good use of this pattern, though. Would it be better to abstract the builder too? Or would a factory pattern better suit my use case?
You have identified the need for an abstract superclass, Reservation. You have also identified the need for specialization in child classes, like GroupReservation, RoomServiceReservation.
What is the motivation for using a builder or factory pattern? If the problem is to create a new instance of a class given a string, a few if statements or a case statement would work fine.
if(userSelection.equals("group")) {
return new GroupReservation();
}
If the motivation is for something more complex, a builder or factory class might be useful. The messy details of selecting and instantiating a concrete class can be hidden that way.
Object-oriented programmers can unwittingly wear "pattern goggles". When we wear pattern goggles, we approach every design choice looking for just the right pattern to implement. Sometimes there is a language feature we can use that eliminates the need for a pattern. And sometimes an if statement is good enough.
GoF book states that there are two ways to implement Factory Method:
Consider the following issues when applying the Factory Method pattern:
Two major varieties. The two main variations of the Factory Method pattern are the case when the Creator class is an abstract
class and does not provide an implementation for the factory method it
declares, and the case when the Creator is a concrete class and
provides a default implementation for the factory method. It’s also
possible to have an abstract class that defines a default
implementation, but this is less common. The first case requires
subclasses to define an implementation, because there’s no reasonable
default. It gets around the dilemma of having to instantiate
unforeseeable classes. In the second case, the concrete Creator uses
the factory method primarily for flexibility. It’s following a rule
that says, “Create objects in a separate operation so that subclasses
can override the way they’re created.” This rule ensures that
designers of subclasses can change the class of objects their parent
class instantiates if necessary.
Parameterized factory methods. Another variation on the pattern lets the factory method create multiple kinds of products. The factory
method takes a parameter that identifies the kind of object to create.
All objects the factory method creates will share the Product
interface. In the Document example, Application might support
different kinds of Documents. You pass CreateDocument an extra
parameter to specify the kind of document to create.
Design Patterns (Design Patterns: Elements of Reusable Object-Oriented Software)
In what cases should I use one approach instead of another. What the benefits and drawbacks when I prefer one approach instead of another?
Thanks in advance.
Kudos for reading the book. Most people attempt #2 believing that is the Factory Method pattern, when in fact #1 claims to describe the two major varieties.
So we're actually dealing with three slightly different versions of the pattern in the quoted text, though only two of them are numbered. The differences between these versions are based on how much information the Creator has about which Product implementation it wants.
A Creator with an abstract Factory Method knows nothing about the Product implementation and leaves everything up to the ConcreteCreator.
A Creator with a default Factory Method knows what Product implementation it wants most of the time, but not always; so it allows a ConcreteCreator to override the default.
A Creator with a parameterized Factory Method has a menu of Product implementations to choose from and decides which one to ask the ConcreteCreator for.
So in each consecutive version, the Creator has progressively more information about the Product implementations and more logic concerning how the implementation is chosen.
In the Factory Method pattern, a Creator delegates responsibility for creating objects to its child classes because it, "can't anticipate the class of objects it must create." (page 108) Based on the different varieties, we can see how the pattern changes slightly when a Creator can anticipate some information about the class of objects to create.
The version you choose depends on how much you know about the Product implementations at compile time.
I have an object that I would like to create. This object is composed of other objects that I don't want the client class to be responsible for creating. There are lots of validation rules that must pass before the object can be created.
So I would like to abstract away the creation of this complex object into a "factory" class. I have 2 questions really, the first is purely about semantics:-
What should I call the class which is creating my object? The factory method pattern and abstract factory pattern are both related to abstracting away creation of concrete classes of different types. However, I'm creating an object of a single type, so using the term factory might be confusing?
Is this an appropriate solution? Are there any patterns/examples of this being done?
Thanks in advance for any help/guidance.
You can use the term factory because we all use it in its broadest sense unless we use a more unique name like Factory Method design pattern or Abstract Factory design pattern.
Builder pattern is typically used if you have an object build process that should still be used if the same master steps should be used in creating different types of objects. But in your case you just have one type. So there's no need for a better solution since there's no special problem to solve. Just do the validation in the simplest form you can.
On page 13 in the GoF book there is a statement:
Two objects of the same type need only share parts of their interfaces.
I am not sure I understand this sentence.
EDIT: full quote might indeed help to understand that
A type is a name used to denote a particular interface. We speak of an
object as having the type "Window" if it accepts all requests for the
operations defined in the interface named "Window." An object may have
many types, and widely different objects can share a type. Part of an
object's interface may be characterized by one type, and other parts
by other types. Two objects of the same type need only share parts of
their interfaces. Interfaces can contain other interfaces as subsets.
In their language, an objects interface is the the entire public contract of the object (Don't think language implementation here).
The set of all signatures defined by an object is called the interface
to the object.
A type is more like what you would think of as a declared interface....
A type is a name used to denote a particular interface.
Imagine:
public class Foo : IBar, IBaz {}
public class Fuz : IBar, IBuz {}
A Foo and a Fuz are both IBar "types" but they only share that aspect of their respective interfaces.
a more full quote is:
A type is a name used to denote a particular interface. We speak of an
object as having the type "Window" if it accepts all requests for the
operations defined in the interface named "Window." An object may
have many types, and widely different objects can share a type. Part
of an object's interface may be characterized by one type, and other
parts by other types. Two objects of the same type need only share
parts of their interfaces. Interfaces can contain other interfaces as
subsets.
and pretty clearly, i think, this is talking about multiple inheritance. for example you might have TextWindow and MenuWindow that both subclass Window along with other classes. both objects can be considered, in the sense they are using, to have "type" Window, and they will both implement the operations associated with that type - they will both have Window's methods. but TextWindow may also subclass TextEditor while MenuWindow does not, so their total set of methods (what they mean by "interface") are not the same, even though the Window part overlaps.
http://www.uml.org.cn/c++/pdf/DesignPatterns.pdf
I don't know what it means as I don't have the book. But an interface is the method signatures of the class, combined with the public variables. As a subtype of a particular type, is also a type of its parent class, it can have methods that it parent does not have, hence it only shares some of the interface of the parent. I have no idea if that is actually what it was talking about though.
In my model all the derived classes have the same ** persistent** attributes and methods as the base abstract class. There are some class specific attributes which aren't persisted and methods have different implementation.
Right now I have about 4 inheriting classes, and I will add more in the future. The nature of the application is that such classes may be added for different uses, so its impossible to know them in advance. The only given is that they will all share the same methods and persistent attributes. The is one column which will be used as discriminator.
I am struggling with strategy. Obviously I don't want to write a ClassMap for each derived class. In fact I's like the persistence layer to be completely ignorant of these derived classes. I am thinking of having the derived classes be able to be created off the base class and to return a base class.
I don't suppose I have any better option?
Your approach is flawed in that the persistence layer can not be ignorant about the subclasses, because it needs to know what the class is when loading/storing.
What you can do is use a convention-based mapping instead of an explicit one (Fluent has Automapping, and ConfORM is convention/override based only), so you don't have to write every classmap.
In ConfORM, it's as easy as saying, for example, orm.TablePerClass<TheBaseClass>(), then mapper.CompileMappingFor(TheBaseClassAndAllItsSubclasses), and you'll get the mappings without any additional effort.