Refactor factory without violating Open Close Principle
I have two versions of a factory class designed based on the article
http://www.oodesign.com/factory-pattern.html
public abstract class Employee
{
    public string Name { get; set; }
    protected string Role { get; set; }
    public abstract string GetRole();
}
public class Manager : Employee
{
    public Manager()
    {
        Role = "MGR";
    }
    public override string GetRole()
    {
        return this.Role;
    }
}
Version 1: Simple, Violates Open Close Principle
Need to change SimpleEmployeeFactory every time, when I add a new concrete class
public class SimpleEmployeeFactory
{
    public static Employee GetEmployee(int typeId)
    {
        switch (typeId)
        {
            case 1:
                return new Manager();
            case 2:
                return new TechnicalLead();
            default:
                return null; //if the id doesn't have any 
        }
    }
}
Version 2:
Refactored Factory, still needs a Concrete Class creation, before we use factory call
public abstract class Employee
{
    public string Name { get; set; }
    protected string Role { get; set; }
    public abstract string GetRole();      
    public abstract Employee createEmployee();
} 
public class ChiefTechnologyOfficer : Employee
{
    public ChiefTechnologyOfficer()
    {
        this.Role = "CTO";
    }
    static ChiefTechnologyOfficer()
    {            
        RefactoredFactory.Instance.registerEmployee(5, new ChiefTechnologyOfficer());
    }
    public override string GetRole()
    {            
        return this.Role;
    }        
    public override Employee createEmployee()
    {
        return new ChiefTechnologyOfficer();
    }
}
Factory
class RefactoredFactory
{
    private static readonly RefactoredFactory instance = new RefactoredFactory();
    static RefactoredFactory()
    {
    }
    private RefactoredFactory()
    {
    }
    public static RefactoredFactory Instance
    {
        get
        {
            return instance;
        }
    }
    private Dictionary<int, Employee> registeredEmployees = new Dictionary<int, Employee>();
    public void registerEmployee(int typeId, Employee employeeInst)
    {
        registeredEmployees.Add(typeId, employeeInst);
    }
    public Employee createEmployee(int typeId)
    { 
        return ((Employee)registeredEmployees[typeId]).createEmployee();
    }
}
Client
 Employee emp = SimpleEmployeeFactory.GetEmployee(1);
 Activator.CreateInstance(typeof(ChiefTechnologyOfficer)); //Avoid
 Employee empFNoR = RefactoredFactory.Instance.createEmployee(5);
 You can see Activator.CreateInstance(typeof(ChiefTechnologyOfficer)) call to make the concrete classes to register themselves with the Factory.  Otherwise we cant retrieve the object  
Is there a way to create a Factory class with out violating OCP principle & with out creating an object like the one I used in RefactoredFactory class?
 It looks like the typeId suffers from Feature Envy .  Instead, define a polymorphic type to capture the type;  eg an interface:  
public interface IEmployeeType
{
    Employee Create()
}
 Now you can define eg a ManagerType , and a TechnicalLeadType , etc. Example:  
public class ManagerType : IEmployeeType
{
    public Employee Create()
    {
        return new Manager();
    }
}
This is essentially an Abstract Factory, and it has the advantage that you can always create a new implementation when you need to create a new sub-type.
If you're at the boundary of a system, and must translate a primitive value like an integer to a polymorphic value, you can use one of the Role Hint patterns - particularly Metadata, Role Interface, or (my favourite) Partial Type Name.
Client
 Given an IEmployeeType instance employeeType , a client would simply go:  
Employee emp = employeeType.Create();
Thala, Instead of using static constructor,register method to populate dictionary of Types. You can use config based solution like .net DbProviderFactory, to register all types.
<EmployeeFactories>
  <add name="manger"  type="Manager, EmployeeAssmbly" />
..
</EmployeeFactories>
                        链接地址: http://www.djcxy.com/p/77772.html
                        上一篇: 是否有初始化通过DI容器创建的对象的模式
下一篇: 重构工厂没有违反开放原则
