缓存机制是在工厂类内部还是外部更好?
我的问题与严格的语言无关,它更多的是一个通用的编程概念。
如果我有一个 Factory 类,它有一个返回 Parser 对象的方法,并且我知道这些解析器类不需要在每个迭代周期实例化一次以上(当然,在工厂之外)。
就使用和对象分离而言,最好为工厂内部的所有实例化解析器创建缓存机制,即:在方法调用期间,还是在方法调用之外,当方法已经被调用时?
提前致谢。
my question here is not strictly language related, it is more a general programming concept.
If I have a Factory class that has a method to return Parser objects, and these parser classes ,I know, do not need to be instantiated more than once per iteration cycle (outside of the factory, of course).
It is better, in terms of use and object separation to create a caching mechanisms for all the instantiated Parsers inside of the Factory, ie: during the method call, or outside of it, when the method has already been called?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
也许您可以为
Factory
定义一个接口,然后有多个实现 - 一个实现可以在内部执行缓存,以保证Parser
类仅实例化一次。另一种实现可以不执行缓存,而只是在需要时提供新的 Parser 对象。无论哪种方式,我建议您尝试将此逻辑保留在
Factory
实现中,并让应用程序的其余部分与Factory
接口一起使用。这样,如果您稍后决定不想缓存任何内容或者需要更改Parser
实例化的方式,则您只有一个对象创建点 - 在内部工厂。这使得更改构造
Parser
对象的方式变得非常容易,而无需更改应用程序中需要新Parser
的每个部分。再说一次 - 如果您创建缓存机制在
Factory
之外操作,那么这些机制将遍布您的代码,因为每当您想要获得新的Parser
时都必须使用它们代码>.如果您稍后决定更改缓存机制,则将不得不接触大量代码,但如果您在Factory
内进行缓存,则只需更改Factory实施。
Perhaps you could define an interface for your
Factory
, and then have multiple implementations - one implementation could perform the caching internally to guarantee that aParser
class is only instantiated once. Another implementation could perform no caching and just provide newParser
objects whenever something asks for one.Either way, I suggest you try to keep this logic inside your
Factory
implementations and have the rest of your application work with theFactory
interface. This way if you decide later that you don't want to cache anything or that you need to change the way aParser
is instantiated, you only have a single point of object creation - inside theFactory
. This makes it really easy to change the way you constructParser
objects without having to change every part of your application that wants a newParser
.Once again - if you create caching mechanisms to operate outside of the
Factory
, then those mechanisms will be all over your code since you have to use them whenever you want to get a newParser
. If you decide later to change the caching mechanism, you're going to have to touch a lot of code, but if you do the caching inside theFactory
, you only have to change theFactory
implementation.我不明白这个问题:工厂类的客户端不关心他们收到的对象是否被缓存。因此缓存逻辑必须属于工厂。
此外,当您实现此功能时,您首先要实现不带缓存的工厂,以便快速运行(做可能有效的最简单的事情)。然后,您实施缓存。请注意,做任何其他事情都是过早优化的情况。如果客户端类必须知道对象是否被缓存,那么您的开发过程将会很快崩溃。
如何实施取决于您。我喜欢编写一次通用缓存类并在这种情况下重用它,但您可以考虑其他机制。此外,我不做java,因此我无法说明在这里做什么更好。
(PS:我在这个问题的答案中看到很多设计模式噪音。java人总是用模式来思考,这是常见的吗?这里没有单例需要设计,没有代理类需要编写,只有一个简单的推理关于哪个接口不能改变)。
I don't understand the problem: the clients of the factory class don't care whether the objects they receive are cached or not. So the caching logic must belong to the factory.
Moreover, when you implement this, you first implement the factory without caching in order to have something working fast (Do the simplest thing that could possibly work). Then, you implement caching. Note that doing anything else is a case of premature optimization. If the client classes had to know whether the objects are cached or not, your development process would rot quickly.
How you implement it is up to you. I like writing once a generic caching class and reuse it in situations like this, but you could think about other mechanisms. Besides, I don't do java and therefore I cannot state about what is better to do here.
(PS: I see a lot of design pattern noise in the answers to this question. Is this common among java people to always think in term of patterns ? There are no singletons to design, no proxy classes to write here, only a simple reasoning about which interface cannot change).
正如 Shakedown 所说,一种方法是针对接口工作并提供缓存实现和单独的非缓存实现。不过,在某些情况下这可能会有点麻烦(您的应用程序真的需要两种不同的实现吗?)。
如果您有许多这样的类,您可以考虑使用代理模式。 Proxy 类将实现与 Factory 实现相同的接口,并且仅当从 Factory 返回的对象尚未在 Proxy 的缓存中时才委托给工厂。
使用动态代理将扩展这种方法,并允许您在任何需要的地方实现缓存,而几乎不需要额外的库膨胀(但代价是复杂性增加)。
As Shakedown stated, one approach would be to work against an interface and supply a caching implementation and a separate non-caching implementation. This can get to be a bit cumbersome in some circumstances though (does your app really need two different implementations?).
If you have a number of classes like this, you might consider using a Proxy pattern. The Proxy class will implement the same interface as the Factory implementation and delegate to the factory only if the object that would be returned from the Factory is not already in the Proxy's cache.
Using a dynamic proxy will extend this approach and allow you to implement caching wherever you want with very little additional library bloat (but at the cost of increased complexity).
我认为问题在于工厂接口提供的合同。这些合约可以使用测试(例如测试 1)进行验证,并且更改实现不应破坏现有行为。将代理编写为缓存会破坏这些约定,因为它将在测试 1 中失败。因此缓存应该是工厂的一部分,并且应该从一开始就如此。请参阅测试 2。
在测试中编写以显示工厂创建“新鲜”对象。
<代码>
var item1 = 工厂.Create();
var item2 = 工厂.Create();
Assert.NotEqual(item1, item2);
编写一个测试来显示工厂缓存对象:
<代码>
var item1 = 工厂.Create();
var item2 = 工厂.Create();
断言.Equal(item1, item2);
I think the question is about the contract the factory interface provides. These contracts can be validated using a test e.g. test 1 and changing implementations shouldn't break existing behavior. Writing a proxy as a cache breaks these contracts as it will fail on test 1. Therefore caching should be part of the factory and it should be from the start. See test 2.
Write at test to show that a factory creates 'fresh' objects.
var item1 = factory.Create();
var item2 = factory.Create();
Assert.NotEqual(item1, item2);
Write a test to show that a factory caches objects:
var item1 = factory.Create();
var item2 = factory.Create();
Assert.Equal(item1, item2);