I will explain a few terms, cited from http://www.dofactory.com/Patterns/PatternFactory.aspx, to conceive the structure easily before digging in the pattern.
Product : defines the interface of objects the factory method creates
Concrete Product : implements the Product interface
Creator : Declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default Concrete Product object. It may also call the factory method to create a Product object
Concrete Creator : overrides the factory method to return an instance of a concrete product.
There are some reasons to choose Factory Method :
- If developer doesn't know which classes should be instantiated before execute business logic purpose.
- If class constructor has complex statements.
- You can apply dependency injection by using Factory Method pattern.
- It helps to build Test Driven Design.
- You can easily prevent to misuse "Concrete" classes.
To show an example of Factory Method Pattern I used Database product which was implemented by MSSQL concrete product and Oracle concrete product. DatabaseFactory creator is responsible for return an object of Database product. In addition, MSSQLDatabaseFactory and OracleDatabaseFactory override factory method ,in this example Create() method, and return an instance of MSSQL or Oracle concrete product.
Lets look at the example below :
1: // product
2: public abstract class Database
3: {
4: public abstract void OpenConnection();
5: }
6:
7: // concrete product
8: internal class MSSQL : Database
9: {
10: private MSSQL() { }
11: public static MSSQL Create() { return new MSSQL(); }
12:
13: public override void OpenConnection()
14: {
15: Console.WriteLine("MSSQL Database connection is ready");
16: }
17: }
18:
19: // concrete product
20: internal class Oracle : Database
21: {
22: private Oracle() { }
23: public static Oracle Create() { return new Oracle(); }
24:
25: public override void OpenConnection()
26: {
27: Console.WriteLine("Oracle Database connection is ready");
28: }
29: }
30:
31: // creator
32: public abstract class DatabaseFactory
33: {
34: public void Run()
35: {
36: Database database = Create();
37: database.OpenConnection();
38: }
39:
40: protected abstract Database Create();
41: }
42:
43: // concrete factory
44: public class MSSQLDatabaseFactory : DatabaseFactory
45: {
46: protected override Database Create()
47: {
48: return MSSQL.Create();
49: }
50: }
51:
52: // concrete factory
53: public class OracleDatabaseFactory : DatabaseFactory
54: {
55: protected override Database Create()
56: {
57: return Oracle.Create();
58: }
59: }
at line 10, 22 : Constructors have private access specify in order to not allow instantiate concrete products by using new keyword. Instead, there are public static method called Create() which returns concrete product.
at line 46,55 : Create() abstract method of DatabaseFactory is overridden and implement statements to return concrete product.
at line 34 : It has all business logic and perform business logic according to concrete product type. DatabaseFactory class doesn't know anything about concrete product. So we can easily create an fake object to write unit tests without invoking concrete product. It gives us to apply test driven development and provide dependency injection.
As you see it's also really easy to expand and add new concrete product for instance MySQL. You can implement MySQL database provider without modifying Creator (DatabaseFactory) and other Concrete Products (MSSQLDatabase or OracleDatabase). This solution reduces to make mistakes.
Using Factory Method Pattern :
1: static void Main(string[] args)
2: {
3: DatabaseFactory factory = new MSSQLDatabaseFactory();
4: factory.Run();
5:
6: factory = new OracleDatabaseFactory();
7: factory.Run();
8:
9: Console.ReadKey();
10: }
at line 3, 6 : factory object doesn't have any information concrete products.
at line 4,7 : Run() method is invoked to perform database operations.
If you try to instantiate concrete product, MSSQL or Oracle, your project cannot be compiled. Because you don't have access to concrete products which are marked as internal.
output is :
MSSQL Database connection is ready
Oracle Database connection is ready




0 comments:
Post a Comment