在我的应用程序中,我想依赖一个类中的多个存储库,每次都不需要所有存储库。我没有在不必要的情况下为每个实例构建一个实例,而是使用了Windsor 中的Typed Factory 工具。
然而,为每个存储库注册一个工厂有点烦人,我想用一个开放的通用注册来代替它。我想要做的是如下所示:
container.Register(
Component.For<IFactory<IRepository<>>>().AsFactory()
);
Run Code Online (Sandbox Code Playgroud)
但是,这是一个语法错误,因为缺少 IRepository 的类型参数。有没有我可以使用的语法来完成这项工作?
注意:我知道我可以注册一个无类型的 Factory 接口并使用它来创建多个组件。我对这样做不感兴趣,因为这基本上依赖于服务定位器 - 如果我没有注册依赖项,那么在代码尝试使用它之前我不会知道它 - 用我知道的方法即使我还没有创建实例,在构造函数中也有 this。
完整(简化)示例如下:
public class TestA { }
public class TestB { }
public interface IRepository<T> { T Create(); }
public class Repository<T> : IRepository<T>
{
public T Create() { return Activator.CreateInstance<T>(); }
}
public interface IFactory<T>
{
T Create();
void Release(T instance);
}
class Program
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
// Individual …Run Code Online (Sandbox Code Playgroud) 假设您有一个返回 ILightBulb 实例的工厂。实现工厂的两种方式(可能还有更多)如下:
enum LightBulbType
{
Incandescent,
Halogen,
Led,
}
class ILightBulbFactory
{
public ILightBulb Create(LightBulbType type)
{
switch (type)
{
case LightBulbType.Incandescent:
return new IncandescentBulb();
case LightBulbType.Halogen:
return new HalogenBulb();
case LightBulbType.Led:
return new LedBulb();
}
}
}
Run Code Online (Sandbox Code Playgroud)
class ILightBulbFactory
{
public ILightBulb CreateIncandescent()
{
return new IncandescentBulb();
}
public ILightBulb CreateHalogen()
{
return new HalogenBulb();
}
public ILightBulb CreateLed()
{
return new LedBulb();
}
}
Run Code Online (Sandbox Code Playgroud)
哪种方法最可取,为什么?
谢谢。
在"清洁代码:敏捷软件工艺手册"一书的第11章中,Bob叔叔说下面的Lazy-Initialization不是一个干净的代码.它需要两个职责,并且具有很强的依赖性.
public Service getService() {
if (service == null)
service = new MyServiceImpl(...); // Good enough default for most cases?
return service;
}
Run Code Online (Sandbox Code Playgroud)
除了IoC容器和工厂,有没有办法让代码干净并与依赖关系分开?
lazy-loading ioc-container inversion-of-control code-cleanup factory-pattern
我找不到一个好的和简单的解决方案来解决我关于不同 bean 生命周期的问题。
我想注入一个
@Resource
private Supplier<MessageHandler> messageHandlerFactory;
Run Code Online (Sandbox Code Playgroud)
在@Servicebean来创建一个新的MessageHandler实例(原型,用自己的依赖),我每次通话时长messageHandlerFactory.get();。
我发现的名为Method Injection的解决方案对于这样一个常见的任务来说似乎过于复杂和繁琐。
使用@Configuration类的最短和最干净的解决方案是什么?
== 更新 ==
spring factory dependency-injection prototype factory-pattern
这可能是一个特殊情况(注入浏览器本机窗口对象),但是当我的类已经有一个@Injectable()装饰器时,我仍然有点困惑为什么我仍然需要@Inject()参数装饰器.
举个简单的例子:
import { provide, bootstrap, Injectable, Inject } from '@angular/core';
@Injectable()
export class Token {
private token: string;
public constructor(token: string, window: Window) {
this.token = window.atob(token);
};
public getToken(): string {
return this.token;
}
}
@Injectable()
export class TokenFactory {
private window: Window;
public constructor(window: Window) {
this.window = window;
}
public createToken(token: string): Token {
return new Token(token, this.window);
}
}
@Component({
template: `
<p *ngFor="let token of tokens">
Encoded: {{token.getToken()}}
</p>
`,
providers: [ TokenFactory ] …Run Code Online (Sandbox Code Playgroud) 当使用 new 运算符创建对象被认为有害时,应该使用工厂模式。新运营商在哪些方面被认为是有害的
所以我试图覆盖__new__并让它作为一个工厂存在来创建派生实例。在阅读了一些关于 SO 的内容后,我的印象是我也应该调用__new__派生实例。
基础事物
class BaseThing:
def __init(self, name, **kwargs):
self.name = name
# methods to be derived
Run Code Online (Sandbox Code Playgroud)
物厂
class Thing(BaseThing):
def __new__(cls, name, **kwargs):
if name == 'A':
return A.__new__(name, **kwargs)
if name == 'B':
return B.__new__(name, **kwargs)
def __init__(self, *args, **kwargs):
super().__init__(name, **kwargs)
# methods to be implemented by concrete class (same as those in base)
Run Code Online (Sandbox Code Playgroud)
一种
class A(BaseThing):
def __init__(self, name, **kwargs):
super().__init__(name, **kwargs)
Run Code Online (Sandbox Code Playgroud)
乙
class B(BaseThing):
def __init__(self, name, **kwargs):
super().__init__(name, **kwargs) …Run Code Online (Sandbox Code Playgroud) 我正在使用带有应用程序工厂模式的烧瓶。我知道应用工厂模式只在工厂函数中管理配置对象。(如下面的代码所示)
def create_app(config):
app.config.from_object(config)
sentry.init(app)
...
return app
Run Code Online (Sandbox Code Playgroud)
但是如何管理需要该配置但无法在应用程序创建时初始化的额外模块?
所以我想做类似的事情
def create_app(config):
some_module_obj = Module(host=config.host, port=config.port)
app.config.from_object(config)
sentry.init(app)
return some_module_obj, app
Run Code Online (Sandbox Code Playgroud)
而不是
# I don't want to use `config` outside of the `create_app` function!
some_module_obj = Module(host=config.host, port=config.port)
def create_app(config):
app.config.from_object(config)
sentry.init(app)
return app
Run Code Online (Sandbox Code Playgroud) 我有一个类,它的负载非常重,因此创建/复制/移动此类的实例非常昂贵。由于应用程序完成初始化后它们不会改变,因此无需创建此类的临时对象。我只需要在容器(std::map)中缓存对象,并在需要时提供“常量引用”。
必须强调的一点是,我正在寻找一种解决方案,可以在将对象添加到容器之前避免双重创建或不必要的复制(我不认为像 @getsoubl 提出的解决方案可以解决问题,因为它不会消除双重创建或不必要的复制)。
因此,我想将构造函数方法安排到类主体的“私有/受保护”部分,以禁止在“工厂方法”之外进行任何创建/复制/移动。以下是我的原始解决方案:
class MyClass {
public:
// methods of the class
static const MyClass & findObject( int iKey ) {
auto pair = mapObjects.try_emplace( iKey, iKey );
if ( pair.second )
cout << "New object has been created" << endl;
return pair.first->second;
};
// deleted
MyClass() = delete;
MyClass( MyClass & ) = delete;
MyClass( MyClass && ) = delete;
MyClass( const MyClass & ) = delete;
MyClass( const MyClass && ) = delete;
MyClass …Run Code Online (Sandbox Code Playgroud) factory-pattern ×10
factory ×2
oop ×2
angular ×1
c++ ×1
code-cleanup ×1
emplace ×1
enums ×1
flask ×1
inheritance ×1
java ×1
lazy-loading ×1
plugins ×1
prototype ×1
python ×1
python-3.5 ×1
spring ×1