Download FactoryPattern.zip - 60.75 KB
Table of Contents
- Motivation
- Introduction
- Background
- Definition
- When to go for Factory Pattern
- Using the Code
- Implementations
- Noob Implementation
- Static Factory with Reflection
- Self Registration without Reflection
- Self Registration with Reflection
- Difference between Factory pattern and Factory Method pattern
- Advantages of Factory Pattern
- Conclusion
- References
Motivation
During my study of design patterns, I used to find the term Factory Pattern very often. I searched the Internet and came across numerous sites. After a lot of search and study I observed that to find the definition of Factory pattern is no tough deal but it took me quite a while to hit upon a simple explicatory implementation of Factory pattern in C#. Most of the examples on Internet are either comprise of Factory Method Pattern or Abstract Factory Pattern. So I decided to write my own article which targets only Factory pattern.
Introduction
An important aspect of software design is the manner in which objects are created. Although far more time is often spent considering the object model and object interaction. But if this simple design (of object creation) aspect is ignored it will adversely impact the entire system. Thus, it is not only important what an object does or what it models, but also in what manner it was created.
I am sure all of us often come across code snippets with switch blocks having the ‘new’ keyword used for instantiating different classes as per client requests. Such a basic mechanism of object creation could result in design problems or added complexity to the design. Factory pattern provides an ideal object creation solution suitable to such situations. Moreover I found that Factory Pattern helps to implement the Open-close Principle, for more information on OCP please checks my first article. In this article I will describe the various implementations of Factory Pattern and pros and cons of each implementation
Background
Although Factory pattern is one of the most widely used patterns, it is not very familiar to many developers. Perhaps the reason is because it is not included in the GOF (gang-of-four) patterns. However, it is worthwhile to note that Factory Pattern is a base for two very popular GOF creational patterns namely Factory method and Abstract Factory pattern.
Alright, I think it’s been enough of a prologue, let us now excavate into the intricacies of this pattern. I will take you through the Definition of Factory pattern and then describe the various implementation of Factory pattern.
Definition
Well as the name suggests, Factory pattern is a creational design pattern which facilitates
Creating objects without exposing the instantiation logic to client.
Referring to the newly created objects through a common interface.
I will describe these two points in more details in incoming sections.
When to go for Factory Pattern
Well, whenever you come across words like kinds or types watch out for application of factory pattern!! At the end of the day it all depends on what the project demands.
Using the code
There are plenty of places where we can apply the Factory pattern. But at this moment let’s consider a familiar example of a Lodging Inquiry system, wherein a customer may wish to get details of different types of available Rooms. Lodging system provides three different types of Rooms (DeluxeRoom, NonACRoom or an ACRoom ). Based on the client choice my system provides the details of specific room. All very well till this point. But just think about how my system might have been designed here?
With no knowledge of factory pattern, a system would have an Interface IRoomType which defines the common behavior for all types of room. All the product-classes (namely ACRoom, DeluxeRoom and NonACRoom) implement this interface. Fair enough till this end, now as per the user request my client application will instantiate the desired class by directly using the new keyword.
Typically the client-code would appear quite like this:
private void GetRoomDetails(string roomType)
{
IRoomType room = null;
switch (roomType)
{
case RoomTypes.AC:
room = new ACRoom();
break;
case RoomTypes.Deluxe:
room = new DeluxeRoom();
break;
case RoomTypes.NonAC:
room = new NonACRoom();
break;
}
room.GetDetails();
}
So, what is the problem with this type of implementation? Well before describing the problem I would like to define one common term “Client application”, which I will use quite frequently. Here I am referring to any window application that can accept, display and store data is said to be client application. Let’s get back to real problem.
- Firstly, we have lots of ‘new’ keyword scattered in the client application. In other words, the client application is loaded with lot of condition based object creational activities which can make the client logic very complicated. What if tomorrow new types of Rooms are added in the lodge? Client application code needs to be changed!
- Client application has to be aware of all the concrete products ( ACRoom, NonACRoom or DeluxeRoom) and their instantiation logic. This methodology often introduces a great deal of the inflexibility in the system, as the direct use of a language/run-time provided object instantiation function creates an explicit association between the creator and created classes
- The coupling introduced between classes is extremely difficult to overcome if the requirements change (as they always do). Just imagine, there comes a season special offer wherein each Non-AC room would be available with a Deluxe Room free of cost! In this case, the constructor of NonACRoom class takes a reference to DeluxeRoom as an argument. Now again the client application needs to be modified and I am sure after listening such a drastic change developer will get heart attack.
- The above mentioned issues might be easy to deal in the case of a small project.But,
- What if the client code is huge and too complex to be modified and retested?
- And what if this inquiry system is being used by multiple lodges in a city
In these cases only God can save whole application.
The failure of above design can be overcome with the aid of Factory pattern. Factory pattern intends to overcome these drawbacks by delegating the task of object creation to a factory-class. The factory-class completely abstracts the creation and initialization of the product from the client-application. This indirection enables the client to focus on its discrete role in the application without concerning itself with the details of how the product (ACRoom, NonACRoom or DeluxeRoom) is created. Thus, as the product initialization changes over time or new types of product get added to the system, the client remains unchanged. The flow diagram for the same goes like this
The Factory pattern has evolved over time and majorly there are four different ways of implementing of this pattern. Throughout the article, I will take Lodging Inquiry system as an example and will describe the pros and cons with each type of implementation. Before going forward please synchronize with enclosed source-code.
- Implementation-1: Procedural Solution/Basic noob implementation also known as parameterized factory.
In noob-implementation we define a singleton-factory-class said to be RoomFactory class. RoomFactory class is responsible to implement a special-function (say GetRoomType). GetRoomType function accepts the user requests as a function-parameter and returns specific product-object, by directly using the ‘new’ keyword. Each product class (say ACRoom, DeluxeRoom or NonACRoom) must have to implement the common interface (IRoomType). IRoomType interface defines the basic properties for room.
Noob-implementation removes the scattered ‘new’ from client code and gets the same in RoomFactory class. This way client-code remains less complicated and unchanged when new products get added to the system. Following code-snippet depicts the implementation of GetRoomType method in RoomFactory class.
internal IRoomType GetRoomType(RoomTypes roomType)
{
IRoomType room = null;
switch (roomType)
{
case RoomTypes.AC:
room = new ACRoom();
break;
case RoomTypes.Deluxe:
room = new DeluxeRoom();
break;
case RoomTypes.NonAC:
room = new NonACRoom();
break;
}
return room;
}
In noob-implementation of factory pattern the code snippets for client-code will be as follows:
private void SubmitButton_Click(object sender, EventArgs e)
{
RoomTypes rmType = (RoomTypes) "ACRoom";
IRoomType roomType = RoomFactory.Singleton.GetRoomType(rmType);
roomType.GetDetails();
}
Advantages and disadvantages of this implementation are as follows.
Advantages:
- Easy to implement.
- Client application code doesn’t have to change drastically.
- Moreover the tight coupling between client and product classes is overcome and turned into coupling between factory and product classes. Hence client need not know the instantiation logic of products.
Disadvantages:
- If we add any new product (room), we need a new case statement in GetRoomType method of Factory class. This violates open/closed design principle.
- We can avoid modifying the Factory class by using sub classing. But Sub classing means replacing all the factory class references everywhere through the code.
- We have tight coupling between Factory class and products
- Implementation-2: Registration with reflection
Noob-implementation of factory pattern is easy to implement but lead to a major setback, violation of open and close principle. Registration with reflection implementation overcomes the problems of noob-implementation. Alright!! Coming back to implementation details, same as Noob-implementation we have product classes (ACRoom, NonACRoom and DeluxeRoom), interface IRoomType (defines basic properties of product) and RoomFactory class but internal implementation differs :).
The registration with reflection implementation works on the analogy unique-key association with product classes (ACRoom, NonACRoom or DeluxeRoom ). Client sends corresponding key to get the specific product.
In registration with reflection implementation client-application must have to associate each product class (DeluxeRoom, ACRoom or NonACRoom) with some unique identifier. The client code to register each product is as follows.
private void RegisterProduct()
{
RoomFactory.Singleton.RegisterRoom(RoomTypes.AC, typeof(ACRoom));
RoomFactory.Singleton.RegisterRoom(RoomTypes.NonAC, typeof( NonACRoom));
RoomFactory.Singleton.RegisterRoom(RoomTypes.Deluxe, typeof( DeluxeRoom));
}
The RoomFactory class contains a hash table/dictionary which stores the mapping between product’s unique-identifier (key) and type/ product class name (value). RegisterRoom method helps to map the unique-identifier with product-class (ACRoom, NonACRoom or DeluxeRoom).The implementation of RegisterRoom method in RoomFactory class is as follows.
public void RegisterRoom(RoomTypes id, Type roomtype)
{
if (m_RoomMapping.ContainsKey(id) == false)
{
m_RoomMapping.Add(id, roomtype);
}
}
The purpose of GetRoomType method in RoomFactory class is same but the implementation is slightly different from the noob-implementation. Here is the code snippet showing product instantiation logic of RoomFactory class:
internal IRoomType GetRoomType(RoomTypes roomType)
{
IRoomType room = null;
if(m_RoomMapping.ContainsKey(roomType))
{
Type className = (Type) m_RoomMapping[roomType];
room = (IRoomType)Activator.CreateInstance(className);
}
return room;
}
The big point to notice in this implementation is that, it is the responsibility of client to register each product class in the RoomFactory class before using it. The factory class then creates product objects as per client requests not by using “new” keyword but using reflection.
Advantages and disadvantages of this implementation are as follows:
Advantages:
-
As the factory class remains unchanged even when new products are added, this implementation doesn't violate the open and closed principle.
-
This implementation provides the loose coupling between Factory class and concrete products. This is because product objects are created using reflection so the factory need not know the instantiation details of product class.
- The client doesn't need to be aware of all the available products. Only the required products need to be registered before use. Moreover product creation is abstracted from the client.`
Disadvantages:
- The client has to register required product classes with the factory, before use.
- Reflection makes system slow.
- Not all the languages support reflection.
- This implementation is more difficult to implement.
-
Implementation-3:Self Registration without reflection
The major problem in previous implementation is reflection makes the system slow. Current implementation (Self registration without reflection) is more or less same to implementation-2 but overcomes the problem of reflection. Same as implementation-2 we have product classes (ACRoom, NonACRoom or DeluxeRoom), RoomFactory class and IRoomType interface. IRoomType interface defines the basic properties for product classes additionally declare CreateProduct method. Signature of IRoomType interface is as follows:
interface IRoomType
{
void GetDetails();
IRoomType CreateProduct();
}
In self-registration-without-reflection implementation IRoomType interface forces each product class (ACRoom, NonACRoom or DeluxeRoom) to implement the CreateProduct method. It is crucial to observe the purpose of CreateProduct method. CreateProduct method returns a new instance of its own type thereby eliminating use of reflection mechanism. The code-snippets of CreateProduct method in NonACRoom product class is as follows.
public IRoomType CreateProduct()
{
return new NonACRoom();
}
In addition to realizing the IRoomType interface, each product class (DeluxeRoom, ACRoom or NonACRoom) must implement a static function RegisterProduct. RegisterProduct method associates the specified key with corresponding product-type using Factory class.
public static void RegisterProduct(RoomTypes roomType)
{
RoomFactory.Singleton.RegisterRoom(roomType, new NonACRoom());
}
Same as previous implementation, we have GetRoomType method in RoomFactory class which returns the corresponding product instance based on client request. Implementation of GetRoomType method in implementation-3 is as follows.
internal IRoomType GetRoomType(RoomTypes roomType)
{
IRoomType room = null;
if(m_RoomMapping.ContainsKey(roomType))
{
room = (IRoomType)m_RoomMapping[roomType];
}
return room.CreateProduct();
}
Since the registration process of products( ACRoom, NonACRoom or DeluxeRoom) is contained within the product class itself, this mechanism is termed as self registration. Fair enough till this end lets come back to client code, client registers each product in RoomFactory in following manner:
private void RegisterProduct()
{
DeluxeRoom.RegisterProduct(RoomTypes.Deluxe);
ACRoom.RegisterProduct(RoomTypes.AC);
NonACRoom.RegisterProduct(RoomTypes.NonAC);
}
Later client code makes use of GetRoomType method of RoomFactory class to get the corresponding room details.
Advantages:
- This implementation gives us the same advantages as in case of Implementation-2.
- Additionally it eliminates use of reflection. This provides considerable performance gain.
Disadvantages:
- The client has to register required product class with the factory before use.
- More difficult to implement
-
Implementation-4:Self Registration with reflection
The problem in previous two implementations (implementation-2 and implementation-3) is product classes (ACRoom, NonACRoom or DeluxeRoom) must have to be registered before using. Self registration with reflection implementation removes the pitfall of previous implementation but make use of reflection. Implementation-4 is almost similar to implementation-2 but the bare difference is the registration is done by RoomFactory class itself. In this implementation, each product class has to define one static property to returns it’s unique identifier.
public static RoomTypes Key
{
get
{
return RoomTypes.NonAC;
}
}
In order to achieve automatic registration, RoomFactory class defines a method, which iterates through all the types within the executing assembly and checks whether the type is a product class (ACRoom, NonACRoom or DeluxeRoom). For example in this case we check whether the type implementsIRoomType interface. For each of these product classes the static unique identifier (Key) is retrieved using reflection mechanism. This unique key is registered in hashtable along with corresponding product class type. The code below describes the registration method of RoomFactory class:
internal void Initialize()
{
Assembly asm = Assembly.GetExecutingAssembly();
Type[] allTypes = asm.GetTypes();
foreach (Type type in allTypes)
{
if (type.IsClass && !type.IsInterface)
{
Type iRoom = type.GetInterface("IRoomType");
if (iRoom != null)
{
RoomTypes roomType = (RoomTypes)type.GetProperty("key",
BindingFlags.Static | BindingFlags.Public).
GetValue(null, null);
if (roomType != null)
{
m_RoomMapping[roomType] = type;
}
}
}
}
}
Definition of GetRoomType method in RoomFactory class is similar to implementation-2 to retrieve the particular product.
Advantages:
Disadvantages:
- Reflection makes system slow.
- Not all the languages support reflection.
Difference between Factory pattern and Factory Method pattern:
While going through this pattern I often felt that this is more or less same as factory-method pattern. I was completely baffled, what is the difference between both? Then I arrived at some really good points.
- Factory pattern is the base for Factory method and abstract factory pattern.
- Here we have just one factory which is intended to create different types of products whereas in factory method pattern we need to have one abstract class which defines the interfaces for several factories.
- The advantage of factory method pattern over factory pattern is that the client is abstracted from both the type of product and the type of factory used to create the product. Presuming that the product interface is invariant, this enables the factory to create any product type it deems appropriate. Furthermore, presuming that the factory interface is invariant, the entire factory along with the associated products it creates can be replaced in a wholesale fashion. Both of these radical modifications can occur without any changes to the client.
Well implementation and description of Factory Method pattern is out of scope of this article. Probably next article would focus on the intricacies of Factory method pattern.
Advantages of Factory Pattern:
One of the eminent facets of a good software design is the principle of loose-coupling or de-coupling, i.e., reducing or removing class dependencies throughout the system. Factory class removes the dependency on the specific product classes generated by the Factory from the rest of the system. The system is only dependent on the single interface type that is generated by the Factory. Loosely coupled or decoupled code is easier to test or reuse since the code has fewer dependencies on other code.
Conclusion:
As per the project requirements, the most suitable implementation of Factory pattern can be deployed in the code. The usage of apt implementation will result in considerable fall of code complexity and fair maintenance of code.
References
- http://msdn.microsoft.com
- http://www.oodesign.com
- http://www.dofactory.com
| You must Sign In to use this message board. |
|
|
 |
|
 |
Nice article, but, in my humble opinion, I wouldn't recommend this solution for complex cases.
Honestly, I think abstract factories should only be used in simple situations. When you come to a point where you need more flexibility, you will want to use a complete Inversion of Control library like these http://elegantcode.com/2009/01/07/ioc-libraries-compared/[^].
To be more specific, let me exemplify. Suppose you want to add a new room type. You would obligatorily have to touch the RoomTypes enumeration. Since your factory depends on this enumeration, you'd have to rebuild the factory to add another room type. Depending on the case, that might be a serious disadvantage. A really good abstract factory does not have any dependencies on the available concrete types.
Another lack of flexibility is in the control over the lifetime of the created objects. Sometimes, you need the created object to be singleton. Some other times, you might need only one instance to be created per each HttpRequest. For example, your hotel might have only one PresidentialSuiteRoom.
What if you need to pass some parameters to the constructor? The guest might want a room in the top floor. Or, making it more complex, he/she might want a room with a view to the beach AND to be at least on the third floor.
To cover all these cases and much more, you definitely need an IoC framework with DI (dependency injection). If you're not familiar with these subjects, I strongly suggest you to study it. It's a very deep and interesting subject.
see ya
|
| Sign In·View Thread·PermaLink | 4.00/5 |
|
|
|
 |
|
 |
The following line in your post is crucially important:
jpbochi wrote: A really good abstract factory does not have any dependencies on the available concrete types.
In fact, avoiding this dependency is precisely the reason for creating factories in the first place. As jpbochi points out, unfortunately all the solutions in the OP's otherwise comprehensive post rely on an enumeration that must be updated whenever a new concrete type is added, and thus they all violate the Open/Closed Principle.
As an alternative to an IoC solution, total loose coupling can be achieved with a simple "plugin" architecture:
1. Instead of using an enumeration type for a key, use an open-ended type (such as a string) and mandate a sound naming policy to avoid name collisions. 2. Place a DLL (or whatever is appropriate for your language) for each concrete type implementing a given interface in some well-known location (e.g. those implementing IFoo could go in the directory C:\MyProg\Plugins\Foo) 3. On program startup, scan each DLL in this directory and call a RegisterType() function in each to register each concrete type.
This way, adding a new concrete type is as simple as deploying a new DLL file to a specific directory. That is how you add concrete types while respecting the OCP.
This also has the obvious efficiency advantage of not having to scan through every type in the assembly, checking for whether it implements a given interface, like the OP's solution #4 does. (Aside: I'm not familiar with .NET, so maybe this is a silly question, but how would that foreach loop in solution #4 find a concrete type anyway if nothing has specifically created an instance of one yet with new? The first attempt to create an object of a given concrete type would come via the factory function itself, so that concrete type would not even appear to exist yet at registration time. I assume .NET loads types lazily -- is that correct?)
WTJW
|
| Sign In·View Thread·PermaLink | 3.00/5 |
|
|
|
 |
|
 |
You're absolutely right. One easy way to remove the dependency on the enumeration is by using another "key" to identify the concrete types.
wtwhite wrote: This also has the obvious efficiency advantage of not having to scan through every type in the assembly, [...]
How would you find the types to register without scanning all types in the assemblies?
wtwhite wrote: [...] how would that foreach loop in solution #4 find a concrete type anyway if nothing has specifically created an instance of one yet with new? The first attempt to create an object of a given concrete type would come via the factory function itself, so that concrete type would not even appear to exist yet at registration time. I assume .NET loads types lazily -- is that correct?
I'll try and answer that. I don't know which language you're more familiar with, but, in .NET, you don't need to instantiate types. In fact, you can't do that. To get a Type instance, you need to call a reflection function, like Assembly.GetTypes().
The foreach in the solution #4 will enumerate through all the types of the current executing assembly and register only a few selected types. In that way, a simple association between a key value and a Type is kept in the factory. No real instances exist at this point. IRoomType instances are created only when GetRoomType() is called.
The authors have chosen Activator.CreateInstance() to create a instance from a Type. Basically, this function will search for a constructor with no parameters for the specified Type and call it.
By the way, looking at the code now, I spotted some possible bugs. A. If a registered type has no parameterless constructor, Activator.CreateInstance() will fail. It might be a good idea to avoid that. Maybe, it would be better to not even register the type; B. If an abstract class implements the IRoomType interface and has the Key property, it would get registered. Since it's impossible to instantiate abstract classes, the factory should not accept registering one; C. The singleton pattern is not thread-safe. This might help: http://msdn.microsoft.com/en-us/library/ms998558.aspx[^].
One last comment. If you don't need/want to use IoC and prefer the approach that wtwhite suggested, you can use the MEF framework (http://www.codeplex.com/MEF[^]). It so useful that Microsoft has included it inside the .NET Framework 4.0, which is still in beta, unfortunately.
thanks! JP
|
| Sign In·View Thread·PermaLink | 4.00/5 |
|
|
|
 |
|
 |
Thanks for the helpful reply. Being largely ignorant of .NET, I went and quickly scanned a tutorial webpage on .NET assemblies to find out what they actually are: according to my mental model of things, it seems that a .NET assembly is basically a .NET-specific DLL or EXE file enhanced with better versioning and type information, and a sound policy ("strong naming") for naming shared assemblies (DLLs).
I was worried that .NET assemblies couldn't be installed "just anywhere" in the filesystem, but then I found this link: http://stackoverflow.com/questions/932339/net-assembly-plugin-security[^], which seems to be doing what I suggested earlier using the Assembly.LoadFile() function. So I suppose a "plugin directory" approach is possible after all.
So, I would suggest that concrete classes be deployed as separate assemblies in a known subdirectory. For easy management, I would recommend 1 concrete type per assembly, although you could certainly group together concrete types that will be deployed together into a single assembly. However, instead of iterating over all types contained in these assemblies as you, the OP and the poster of the above link propose, I suggest that it's much healthier to have each assembly provide a function, called say RegisterTypes(), which will register all relevant types in that assembly. This way, the decisions regarding which types in a given assembly get registered are made entirely by the assembly itself, so it's not possible to accidentally add types that "shouldn't" be added, such as mock/test versions of classes (it's impossible to determine these by any programmatic means, even if other cases such as abstract classes can be tested for via reflection).
If you put just 1 or a small number of concrete classes, and nothing else, into an assembly, then the speed impact of looping over all types in an assembly with GetTypes() will be very small -- but having RegisterTypes() just explicitly list the types will always be fast, even if that's not the case. It's still low-maintenance, since each assembly contains only 1 or a small number of concrete classes to register.
Your comments regarding constructors that need parameters are sound, though I think this is a more general problem. (Like most problems, it can be solved with another level of indirection: require all constructors for classes implementing IFoo to take a single argument of type IFooConstructorArgument, an interface type which lumps together all parameters; then establish a parallel hierarchy of concrete types implementing this interface, and have each IFoo-derived constructor downcast its argument appropriately.)
The languages I'm most familiar with are C and C++ BTW.
|
| Sign In·View Thread·PermaLink | 4.00/5 |
|
|
|
 |
|
 |
I almost completely agree with you. A RegisterTypes() function per assembly would be much better than scanning all types in each assembly. It would even be possible for a assembly to decide dynamically which types to register.
The reason for the "almost" above is this: In .NET, you cannot define a function outside a class. So, you would have to declare the RegisterTypes() function inside a class; and, in order to find it, you would have to find this class. You fall back to a similar problem. How to find a specific class inside an assembly?
One simplistic solution would be to settle a constant name for the class, but an assembly can easily have more than one class with the same name by placing them in different namespaces. I have thought about this and I think I've found a good solution using Custom Attributes (http://msdn.microsoft.com/en-us/library/sw480ze8%28VS.100%29.aspx[^]). Specifically, I would use an assembly attribute that points to the class where the RegisterTypes() function is.
Since a code snippet is worth some hundreds of words, here is how the attribute declaration would look like:
[AttributeUsage(AttributeTargets.Assembly)] public class PluginAttachPointAttribute : Attribute { public Type AttachPoint { get; private set; } public PluginAttachPointAttribute(Type attachPoint) { this.AttachPoint = attachPoint } }
And here is how an user assembly would use it:
[assembly: PluginAttachPoint(typeof(TypeProvider))]
class TypeProvider { Type[] RegisterTypes() { } }
I have ran into similar problems in the past, but I haven't thought about using an assembly custom attribute before. There might be some catches around it. Anyway, I guess this discussion has expanded my mind in this point. 
thanks! JP
|
| Sign In·View Thread·PermaLink | 4.00/5 |
|
|
|
 |
|
 |
Yes, allowing the assembly to decide dynamically which types to register is a good idea which I hadn't considered. RegisterTypes() could e.g. check aspects of the environment and decide whether to register NTFSFoo or FAT32Foo or both.
jpbochi wrote: In .NET, you cannot define a function outside a class.
All that is necessary is that a function for registering types must somehow be locatable within each assembly. It looks like your approach of using assembly attributes is a good way to do that.
BTW, I can't claim any credit for these ideas for how to organise plugins -- they basically come straight from how COM does things. There are a lot of good ideas in COM, though it took me a while to fully appreciate them. Unfortunately the process of creating and using COM objects was never as simple and natural as it is with .NET objects, because it was designed for a native code environment without good infrastructural support (type safety etc.).
And yes, I've certainly learned heaps from this discussion! Glad the feeling's mutual 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
It does suggest that it might be worth while also creating an interface for the
interface IFactoryObject { string Key{get;}
IFactoryObject CreateObject(); }
and on the abstract base factory creating
public abstract RegisterFactoryObject(IFactoryObject obj)
Although it's not that neat in that you if you register and IRoom :IFactoryObject and you get back an IDinner :IFactoryObject bad things will happen.
Great article Thanks, Matthew @ pelsys
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I like this article very much. You gave a clear explanation of the topic, showed the advantages and disadvantages of different approaches, and showed out it fit into the larger picture of patterns in general. Nice job.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Article Looks Good ! One small suggestion, It would be better if you provide hyperlink to the table content.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Isn't the class diagram at the bottom labeled FactoryMethodPattern actually a depiction of an Abstract Factory?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello,
Thanks for reading through my article. It’s always nice to receive some feedback 
Well, with regards to your question the answer goes like this...
Factory Method Pattern provides an interface for creating an object, but let subclasses decide which class to instantiate.
Whereas Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.
The diagram I have shown depicts Factory method pattern as I am creating an object of type Room only. Notice that there is only one Abstract product type i.e. IRoomType in this case.
If I were to depict Abstract Factory Pattern, it would mean I am creating families of related/dependent objects. For e.g.
1 family could be - AC Room, AC Kitchen, AC Library
2nd - NonAC Room, NonAC Kitchen, NonAC Library
3rd - Deluxe Room, Deluxe Kitchen, Deluxe Library
In this case, the class diagram would be as follows:
<img src="http://img34.imageshack.us/img34/6554/absfactory.th.png" border="0">
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
In a tile game, I declared an interface for the tile objects, and then an interface for a tile-object factory. Then I wrote a method to build a dictionary of tile-object factories. I don't like the use of reflection for such purposes, because it assumes that (1) identifiers used in code will have meaning to the end user, and (2) if self-registering classes are used, it assumes that the mere existence of a class is sufficient reason to expose it to the end user.
If wishes to have the ability to add or remove tile types by adding and removing source files, one may define a partial class called TileRegistrar which defines a Startup event that accepts a callback delegate via which tile classes may register, and a RegisterAll method which accepts a delegate which will be passed to the event. Other source files containing tile class definitions could also contain partial class definitions for TileRegistrar, each containing a uniquely-named Startup event handler which would register any class definitions as appropriate.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|