Try to get the data from the cache, and return if the data exists; otherwise, get the data from the data source, put it in the cache, and return.
Are you familiar with the above logical description? If you use caching extensively in your application, the above logic is likely to appear many times. For example:
This logic seems to be relatively simple, but in practical applications, getting data from the data source may not simply call a method, but require collaboration between multiple classes, transaction control, etc., and the reading and writing of the cache may be more complex than the above example. Therefore, a highly readable approach is to provide three independent methods (read cache, read data source, write cache), so that a method with cache only needs to simply implement the read-write logic mentioned above.
As we said at the beginning of this article, if you use caching extensively in your application, the above logic is likely to appear many times. To some extent, this kind of repetition is redundant, which violates the dry principle. Therefore, we try to provide a base class to encapsulate this cache read-write logic:
The application of the typical "template method" pattern is really Elegance? This is obviously "overcorrection"! A getfriends method needs to develop a class, and there should be dozens or hundreds of such methods in the application, right? Therefore, we have developed tens of hundreds of subclasses of cachereader. Each subclass needs to encapsulate all the used objects and data, and implement three abstract methods -- OMG. It's really "OOP" to the extreme!
Fortunately, we can use anonymous methods. To do this, we write a helper method:
Delegation is a good thing to use as a parameter of a method, and the presence of anonymous methods makes it particularly useful. For example, we can now:
Does it look weird? In fact, it's good to get used to it. There are many advantages to this approach:
- Good readability: the operation logic is divided into different blocks.
- Easy to program: it can directly use method parameters and external objects, without the trouble of encapsulation.
- Easy debugging: after setting breakpoints, you can easily see the process of "read from cache", "read from data source" and "write to cache".
After the emergence of anonymous methods, this method of passing delegates in as parameters has become very common. For example, the same call mode can be used in the parallel library launched by Microsoft:
Have you accepted this practice?
Are you good at using anonymous functions?