Memory is a design pattern derived from process language such as Lisp, Python, and Perl, which can be memorized for the previous calculation results.
A function that implements a memory function, with explicit Cache, so the result has been calculated directly from cache without each calculation. Memory can significantly improve the efficiency of large computing amount code. And it is a reusable solution. This article describes the method of using this mode in Java, and provides a "memory class" that provides the above functions: foo foo = (foo) Memoizer.Memoize (New fooiMPL () Here, the foo is an interface, which is a way to be remembered. FooIMPL is an implementation of FOO. FOO is a reference to the foo. The method is basically the same as FooIMPL, the difference between the Foo returned, will be cached. The advantage of a single memory class is that it is very simple to add a memory function for any class: Define an interface that contains methods that requires memory, then calls Memoize to implement an instance. In order to understand how the memory class is implemented, we will take a few steps. Explanation. First, I explain why the cache can be implemented in a class that needs it. Then I test how to add a cache wrapper for a specific class. Finally, I explain how to make a cache wrapper can be used for arbitrary Class. Adding a cache for large computing quantities as an example of a large computing quantity program, we consider PibinaryDigitscalculator this example - calculate binary data Pi. Only public method CalculateBinaryDigit has a parameter: integer n, representative needs to be accurate Number. For example, 1000000 will return a million bits after the decimal point, return through the byte value - 0 or 1. (algorithm can be referenced: http://www.cecm.sfu.ca/~pborwein/ PAPERS / P123.pdf) public class PiBinaryDigitsCalculator {/ ** * Returns the coefficient of 2 ^ n in the binary * expansion of pi. * @param n the binary digit of pi to calculate. * @throws ValidityCheckFailedException if the validity * check Fails, this means the implementation is buggy * or n is to large for sufficient prec ISION TO BE * RETAINED. * / Public Byte CalculateBinaryDigit (Final Int N) {Return Runbbpalgorithm (n);} private bote runbbpalgorithm (Final Int N) {// length} The simplest and straightforward method cache the return value can be achieved by modifying this class: Add a Map to hold the value previously calculated, as follows: import java.util.HashMap; public class PiBinaryDigitsCalculator {private HashMap cache = new HashMap (); public synchronized byte calculateBinaryDigit (final INT N) {final integer n = new integer (n); byte b = (byte) cache.get (n); if (b == null) {byte b = runbbpalgorithm (n); cache.put (n, new BYTE (b)); RETURN B;} else {return b.bytevalue ();
}}}} Private bote runbbpalgorithm (Final INT N) {// length}} CalculateBinaryDigit method first checks if this keyword is cached in HashMap, if you find it, return this value directly. Otherwise This lengthy calculation is performed, and the results are saved to the cache. Small conversions are required between the original type and objects when adding to HashMap. Although this method is feasible, but there are several Disadvantages. First, the cached code and normal algorithm code are not significantly separated. A class is not only responsible for calculation, but also to maintain the cache data. This way, it will be very difficult. For example, you can't write A test program to test this algorithm continuously return the same value, because from the second start, the result is obtained from cache. Secondly, when the cache code is no longer needed, remove it will become difficult because It is closely combined with the algorithm block code. So, if you want to know if the cache has brought a high efficiency improvement, it is difficult to write a test program is separated from the cache data. When you improve it Your algorithm, cache is likely to fail - but you don't know. Third, the cache code cannot be reused. Although the code follows a normal model, it is in a class - PibinaryDigitscalculator. In front of the previous two questions You can solve it by constructing a cache wrapper. Cache wrapper is easy to separate computing code and cache code by using Decorator mode. First, define an interface, define basic methods. Public interface binarydigitscalculator {public byte calculatebinaryDigit final int n);} then define two implementations, are responsible for two tasks: public class PiBinaryDigitsCalculator implements BinaryDigitsCalculator {public byte calculateBinaryDigit (final int n) {return runBBPAlgorithm (n);} private byte runBBPAlgorithm (final int n) {/ / Lengthy R outine goes here ...}} import java.util.HashMap; public class CachingBinaryDigitsCalculator implementsBinaryDigitsCalculator {private BinaryDigitsCalculator binaryDigitsCalculator; private HashMap cache = new HashMap (); public CachingBinaryDigitsCalculator (BinaryDigitsCalculator calculator) {this.binaryDigitsCalculator = calculator;} public synchronized byte CalculateBinaryDigit (int N) {final integer n = new integer (n); byte b = (byte) cache.get (n); if (b == null) {byte b = binarydigitscalculator.calculatebinaryDigit (n); cache.put (N, new byte (b)); return b;} else {return b.bytevalue ();