在不违反开闭原则的情况下重构工厂

本文关键字:情况下 重构 工厂 原则 | 更新日期: 2023-09-27 17:49:33

我有两个基于文章

设计的工厂类版本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;
    }
}

版本1:简单,违反开闭原则

需要改变SimpleEmployeeFactory每次,当我添加一个新的具体类

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 
        }
    }
}

版本2:

重构的工厂,仍然需要一个具体类的创建,在我们使用工厂调用

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();
    }
}
工厂

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();
    }
}

 Employee emp = SimpleEmployeeFactory.GetEmployee(1);
 Activator.CreateInstance(typeof(ChiefTechnologyOfficer)); //Avoid
 Employee empFNoR = RefactoredFactory.Instance.createEmployee(5);

您可以看到Activator.CreateInstance(typeof(ChiefTechnologyOfficer))调用使具体类向工厂注册自己。否则我们无法检索对象

有没有一种方法可以在不违反OCP原则的情况下创建工厂类?没有创建一个像我在RefactoredFactory类中使用的对象吗?

在不违反开闭原则的情况下重构工厂

看起来typeId遭受了功能嫉妒。相反,定义一个多态类型来捕获类型;例如接口:

public interface IEmployeeType
{
    Employee Create()
}

现在您可以定义例如ManagerTypeTechnicalLeadType等。例子:

public class ManagerType : IEmployeeType
{
    public Employee Create()
    {
        return new Manager();
    }
}

这本质上是一个抽象工厂,它的优点是当你需要创建一个新的子类型时,你总是可以创建一个新的实现。

如果你在一个系统的边界,并且必须将一个原始值(如整数)转换为多态值,你可以使用角色提示模式之一-特别是元数据,角色接口,或者(我最喜欢的)部分类型名称。

给定IEmployeeType实例employeeType,客户端将简单地执行:

Employee emp = employeeType.Create();

不使用静态构造函数,而是使用注册方法来填充类型字典。你可以使用基于配置的解决方案,如。net DbProviderFactory,来注册所有类型。

<EmployeeFactories>
  <add name="manger"  type="Manager, EmployeeAssmbly" />
..
</EmployeeFactories>