Use*_*ser 86 c# oop design-patterns factory
最近我一直在考虑保护我的一些代码.我很好奇如何确保永远不能直接创建对象,而只能通过工厂类的某种方法创建.让我们说我有一些"业务对象"类,我想确保这个类的任何实例都有一个有效的内部状态.为了实现这一点,我需要在创建对象之前执行一些检查,可能在其构造函数中.这一切都没问题,直到我决定将此检查作为业务逻辑的一部分.那么,我如何安排业务对象只能通过我的业务逻辑类中的某种方法创建,但从不直接?使用C++的旧"朋友"关键字的第一个自然愿望是C#无法实现.所以我们需要其他选择......
让我们试试一些例子:
public MyBusinessObjectClass
{
public string MyProperty { get; private set; }
public MyBusinessObjectClass (string myProperty)
{
MyProperty = myProperty;
}
}
public MyBusinessLogicClass
{
public MyBusinessObjectClass CreateBusinessObject (string myProperty)
{
// Perform some check on myProperty
if (true /* check is okay */)
return new MyBusinessObjectClass (myProperty);
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
这一切都没关系,直到你记得你仍然可以直接创建MyBusinessObjectClass实例,而无需检查输入.我想完全排除这种技术可能性.
那么,社区对此有何看法?
Jon*_*eet 61
您可以将构造函数设为私有,并将工厂设置为嵌套类型:
public class BusinessObject
{
private BusinessObject(string property)
{
}
public class Factory
{
public static BusinessObject CreateBusinessObject(string property)
{
return new BusinessObject(property);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为嵌套类型可以访问其封闭类型的私有成员.我知道这有点限制,但希望它会有所帮助......
Ric*_*lde 56
看起来你只想在创建对象之前运行一些业务逻辑 - 那么为什么不在"BusinessClass"中创建一个静态方法来执行所有脏的"myProperty"检查工作,并使构造函数变为私有?
public BusinessClass
{
public string MyProperty { get; private set; }
private BusinessClass()
{
}
private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}
public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty
if (/* all ok */)
return new BusinessClass(myProperty);
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
调用它将非常简单:
BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);
Run Code Online (Sandbox Code Playgroud)
Fab*_*ied 50
或者,如果你想真正想要的话,反转控制:让班级返回工厂,并用可以创建班级的代表来检测工厂.
public class BusinessObject
{
public static BusinessObjectFactory GetFactory()
{
return new BusinessObjectFactory (p => new BusinessObject (p));
}
private BusinessObject(string property)
{
}
}
public class BusinessObjectFactory
{
private Func<string, BusinessObject> _ctorCaller;
public BusinessObjectFactory (Func<string, BusinessObject> ctorCaller)
{
_ctorCaller = ctorCaller;
}
public BusinessObject CreateBusinessObject(string myProperty)
{
if (...)
return _ctorCaller (myProperty);
else
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
:)
除了Jon建议之外,您还可以将工厂方法(包括检查)放在BusinessObject的静态方法中.然后,将构造函数设置为private,并且其他所有人都将被强制使用静态方法.
public class BusinessObject
{
public static Create (string myProperty)
{
if (...)
return new BusinessObject (myProperty);
else
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
但真正的问题是 - 为什么你有这个要求?将工厂或工厂方法移到课堂上是否可以接受?
这么多年后,这个问题被问到了,不幸的是,我看到的所有答案都在告诉您应该如何编写代码,而不是给出直接的答案。您正在寻找的实际答案是使用私有构造函数但使用公共实例化程序来创建类,这意味着您只能从其他现有实例中创建新实例...仅在工厂中可用:
您的课程的界面:
public interface FactoryObject
{
FactoryObject Instantiate();
}
Run Code Online (Sandbox Code Playgroud)
你的班:
public class YourClass : FactoryObject
{
static YourClass()
{
Factory.RegisterType(new YourClass());
}
private YourClass() {}
FactoryObject FactoryObject.Instantiate()
{
return new YourClass();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,工厂:
public static class Factory
{
private static List<FactoryObject> knownObjects = new List<FactoryObject>();
public static void RegisterType(FactoryObject obj)
{
knownObjects.Add(obj);
}
public static T Instantiate<T>() where T : FactoryObject
{
var knownObject = knownObjects.Where(x => x.GetType() == typeof(T));
return (T)knownObject.Instantiate();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,如果您需要用于实例化或预处理您创建的实例的额外参数,则可以轻松修改此代码。由于类构造函数是私有的,因此此代码将允许您通过工厂强制实例化。
| 归档时间: |
|
| 查看次数: |
45760 次 |
| 最近记录: |