将工厂注入 A Class
Injecting A Factory Into A Class
我正在开发用于生成某种字符串的应用程序功能。我有一个界面:
interface IStringGenerator
{
string GenerateNext();
}
现在我已经在 class 中实现了这个接口,它有一个构造函数和一个参数:
class FixedLengthStringGenerator : IStringGenerator
{
// The class needs some dependencies, but I ignored them here to keep it simple
public FixedLengthStringGenerator(int length /*and dependencies*/)
{ . . . }
public string GenerateNext()
{ . . . }
.
.
.
}
此实现仅生成固定给定长度的所需字符串 length
。 GenerateNext()
每次调用 returns 一个想要的字符串,直到没有剩余然后它 returns null
。考虑到这些,我需要 IStringGenerator
的另一个实现,它可以生成长度介于最小值和最大值之间的字符串。我认为有这样的东西是很自然的:
class MinMaxLengthStringGenerator : IStringGenerator
{
int _MinLength;
int _MaxLength;
int _Length;
IStringGenerator _StringGenerator;
public MinMaxLengthStringGenerator(int minLength, int maxLength)
{
_MinLength = minLength;
_MaxLength = maxLength;
_Length = minLength;
_StringGenerator = new FixedLengthStringGenerator(_Length);
}
public string GenerateNext()
{
if(_Length > _MaxLength)
return null;
string generatedString = _StringGenerator.GenerateNext();
if(generatedString == null)
{
_Length++;
if(_Length <= _MaxLength)
{
_StringGenerator = new FixedLengthStringGenerator(_Length);
return _StringGenerator.GenerateNext();
}
else
return null;
}
else
return generatedString;
}
}
但是直接创建实例并不是一个好主意。相反,我可以使用工厂来获取 FixedLengthStringGenerator
的实例。但我仍然认为这不是一个好的做法,因为它取决于 FixedLengthStringGenerator
。而且如果我以后想用别的替代方案class,这样就无法从外面接收了
我的问题是将工厂注入我的 MinMaxLengthStringGenerator
是否正确(从模式的角度来看)?
更准确地说,考虑
interface IFixedLengthStringGeneratorFactory
{
FixedLengthStringGenerator Create(int length);
}
我应该像下面这样声明 MinMaxLengthStringGenerator
的构造函数吗?
public MinMaxLengthStringGenerator(int minLength, int maxLength, IFixedLengthStringGeneratorFactory factory)
{ . . . }
我认为你非常接近。考虑一个实现这个接口的工厂:
interface IStringGeneratorFactory
{
IStringGenerator CreateFixedLengthStringGenerator(int length);
IStringGenerator CreateMinMaxLengthStringGenerator(int minLength, int maxLength, IStringGeneratorFactory factory);
/* other types? */
}
你在 MinMaxLengthStringGenerator
内分配给 _StringGenerator
然后变成这样:
_StringGenerator = _stringGeneratorFactory.CreateFixedLengthStringGenerator(_Length);
这会从 MinMaxLengthStringGenerator
中删除对 FixedLengthStringGenerator
的具体实现的引用。
希望对您有所帮助!
已更新
那么设计就是这样。
尽管应该尽可能避免在构造函数中注入参数。
现在,我们可以通过任何标准 DI 容器注入依赖项,即 Unity、AutoFac、Ninject
interface IStringGenerator
{
string GenerateNext();
}
class FixStringGenerator:IStringGenerator
{
public FixStringGenerator(int length)
{
...
}
public string GenerateNext()
{
///logic
}
...
}
并且对于 MinMax 字符串生成器 class 如下注入 FixStringGenerator
class MinMaxStringGenerator:IStringGenerator
{
....
IStringGenerator _fixStringGenerator;
public MinMaxStringGenerator(int minLength,int maxLength, IStringGenerator fixStringGenerator)
{
_fixStringGenerator=fixStringGenerator;
}
string GenerateNext()
{
/// do the things with fix generator "_fixStringGenerator"
}
....
}
@Mostafa,依赖注入需要通过实例注册这两个实现,以便它可以创建各自的实例。 HOW TO DI named instance with constructor injection
有关 DI 的更多信息 another link
我正在开发用于生成某种字符串的应用程序功能。我有一个界面:
interface IStringGenerator
{
string GenerateNext();
}
现在我已经在 class 中实现了这个接口,它有一个构造函数和一个参数:
class FixedLengthStringGenerator : IStringGenerator
{
// The class needs some dependencies, but I ignored them here to keep it simple
public FixedLengthStringGenerator(int length /*and dependencies*/)
{ . . . }
public string GenerateNext()
{ . . . }
.
.
.
}
此实现仅生成固定给定长度的所需字符串 length
。 GenerateNext()
每次调用 returns 一个想要的字符串,直到没有剩余然后它 returns null
。考虑到这些,我需要 IStringGenerator
的另一个实现,它可以生成长度介于最小值和最大值之间的字符串。我认为有这样的东西是很自然的:
class MinMaxLengthStringGenerator : IStringGenerator
{
int _MinLength;
int _MaxLength;
int _Length;
IStringGenerator _StringGenerator;
public MinMaxLengthStringGenerator(int minLength, int maxLength)
{
_MinLength = minLength;
_MaxLength = maxLength;
_Length = minLength;
_StringGenerator = new FixedLengthStringGenerator(_Length);
}
public string GenerateNext()
{
if(_Length > _MaxLength)
return null;
string generatedString = _StringGenerator.GenerateNext();
if(generatedString == null)
{
_Length++;
if(_Length <= _MaxLength)
{
_StringGenerator = new FixedLengthStringGenerator(_Length);
return _StringGenerator.GenerateNext();
}
else
return null;
}
else
return generatedString;
}
}
但是直接创建实例并不是一个好主意。相反,我可以使用工厂来获取 FixedLengthStringGenerator
的实例。但我仍然认为这不是一个好的做法,因为它取决于 FixedLengthStringGenerator
。而且如果我以后想用别的替代方案class,这样就无法从外面接收了
我的问题是将工厂注入我的 MinMaxLengthStringGenerator
是否正确(从模式的角度来看)?
更准确地说,考虑
interface IFixedLengthStringGeneratorFactory
{
FixedLengthStringGenerator Create(int length);
}
我应该像下面这样声明 MinMaxLengthStringGenerator
的构造函数吗?
public MinMaxLengthStringGenerator(int minLength, int maxLength, IFixedLengthStringGeneratorFactory factory)
{ . . . }
我认为你非常接近。考虑一个实现这个接口的工厂:
interface IStringGeneratorFactory
{
IStringGenerator CreateFixedLengthStringGenerator(int length);
IStringGenerator CreateMinMaxLengthStringGenerator(int minLength, int maxLength, IStringGeneratorFactory factory);
/* other types? */
}
你在 MinMaxLengthStringGenerator
内分配给 _StringGenerator
然后变成这样:
_StringGenerator = _stringGeneratorFactory.CreateFixedLengthStringGenerator(_Length);
这会从 MinMaxLengthStringGenerator
中删除对 FixedLengthStringGenerator
的具体实现的引用。
希望对您有所帮助!
已更新 那么设计就是这样。
尽管应该尽可能避免在构造函数中注入参数。 现在,我们可以通过任何标准 DI 容器注入依赖项,即 Unity、AutoFac、Ninject
interface IStringGenerator
{
string GenerateNext();
}
class FixStringGenerator:IStringGenerator
{
public FixStringGenerator(int length)
{
...
}
public string GenerateNext()
{
///logic
}
...
}
并且对于 MinMax 字符串生成器 class 如下注入 FixStringGenerator
class MinMaxStringGenerator:IStringGenerator
{
....
IStringGenerator _fixStringGenerator;
public MinMaxStringGenerator(int minLength,int maxLength, IStringGenerator fixStringGenerator)
{
_fixStringGenerator=fixStringGenerator;
}
string GenerateNext()
{
/// do the things with fix generator "_fixStringGenerator"
}
....
}
@Mostafa,依赖注入需要通过实例注册这两个实现,以便它可以创建各自的实例。 HOW TO DI named instance with constructor injection
有关 DI 的更多信息 another link