Data Mapper pattern and duplicate objects
I'm using the data mapper pattern in a PHP app I'm developing and have a question. At present, you request a Site object with a specific ID and the mapper will lookup the row, create an object and return it. However, if you do this again for the same Site you end up with two different objects with identical data. eg.:
$mapper = new Site_Mapper();
$a = $mapper->get(1);
$b = $mapper->get(1);
$a == $b // true
$a === $b // false
So, my question is, should I:
I'd go with caching somehow - static mapper classes would be my first choice, and is what I've seen most of. Otherwise, your option 2 (which is the singleton pattern) is probably the best option.
Remember you need to clear this cache when an update is made to avoid returning stale data.
Having said that, unless you are making something to get a lot of use or that does a lot of queries, it may not matter. (your 4)
Also worth looking at for guidance (I'm sure there are many examples, I just know this one best), Propel (http://propel.phpdb.org/) has the caching feature - might be worth looking at how it does it? Or just use it maybe?
What you're looking for is the Identity Map pattern. Be careful with so called "reading inconsistencies", though. While you use an "old instance", the DB might have been changed already. And while you edit your object, another user might get an instance of it, change it faster and save it faster. Then the other object overrides all these changes again. On the web though maybe not such a big problem since a "page" quickly runs through and no object survives for longer than a few fractional seconds.
I know the question was asked quite a while ago still wanted to answer just in case if someone else runs in a similar dilemma. Actually the above suggestions #1,2,3 that author made are all related and one should consider them all in order to solve the problem.
1) Store each retrieved from DB object in a mapper so that you don't have to do it again when object with the same ID is requested. In all subsequent calls the mapper should return the stored object. This is called IdentityMap pattern. To achieve this make a private property in your mapper to hold an instance of an IdentityMap for a given object type. The Site_Mapper->get() method should always check the IdentityMap for a given ID if the object is not retrieved yet the mapper will go to the database but if it's already stored in the map it returns the cached instance which saves the trip to the database. So then $a === $b should be true because they would be references to the same object instance.
2) Yes ideally there should always be one instance of the given data mapper (Site_Mapper) in order to maintain a single instance of the IdentityMap at a given time. This can be done using Singleton pattern. This is possible with some getter method like Site_Mapper::getInstance() which will always return the same instance of a given mapper. You'd also have to declare the __construct() as a private method to prevent unwanted instantiation using new and make sure getInstance() is the only way to instantiate a mapper.
3) What the author mentioned above about static properties is true as well. To implement a Singleton in PHP one has to use a static property to hold and instance of a Mapper.
I would highly recommend Martin Fowler's book "Patterns of Enterprise Application Architecture" which talks about the above mentioned patterns and many more. It's a good read especially if you're working on your own custom ORM solution. Hope that helps.
链接地址: http://www.djcxy.com/p/56248.html下一篇: 数据映射器模式和重复对象