Dynamic Agent Class in Java Realizing Memory (1)

zhaozj2021-02-16  124

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, 100,00000, will return one million bits after the decimal point, return through the BYTE value - per bit is 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 too large for sufficient precision to be * retained * / public byte calculateBinaryDigit (final int n) {return runBBPAlgorithm (n);} private byte runBBPAlgorithm (final int n) {// Lengthy routine goes here. ..}}

The simplest method to cache the return value can be implemented by modifying this class: adding a map to save the previously calculated value, 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 byte RunbbPalgorithm (Final INT N) {// Length Routine Goes Here ...} CalculateBinaryDigit method first checks if this keyword is cached in HashMap, if found, return this value directly. Otherwise, this will be conducted. Length of lengthy calculations and saves the results into the cache. Small conversions are required between the original type and objects when adding to HashMap. Although this method is feasible, there are several shortcomings. First, The cache code and normal algorithm code are not significantly separated. A class is not only responsible for calculation, but also responsible for maintaining cache data. This way, it is difficult to perform some tests. For example, you cannot write a test program to test This algorithm continues to return the same value, because from the second beginning, the result is obtained directly from Cache. Second, when the cache code is no longer needed, remove it will become difficult because it and the algorithm block The code is closely combined. So, if you want to know if the cache has brought high efficiency improvement, it is also difficult to write a test program is separated from the cache data. When you improve your algorithm, cache It is possible to fail - but you don't know this time. Third, the cache code cannot be reused. Although the code complies with a normal model, it is in a class - PibinaryDigitscalculator. Both the two questions can be constructed by constructing a cache The wrapper is solved. Cache The wrapper is easy to separate computing code and cache code by using Decorator mode. First, define an interface that defines a basic method.

Public interface binarydigitscalculator {public Byte CalculateBinaryDigit (Final Int n);}

Then define two implementations, which are responsible for both tasks:

public class PiBinaryDigitsCalculator implements BinaryDigitsCalculator {public byte calculateBinaryDigit (final int n) {return runBBPAlgorithm (n);} private byte runBBPAlgorithm (final int n) {// Lengthy routine 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 = binarydigitscalcalculator.calculatebinarydigit (n); cache.put (n, new byte (b)); return b;} else { Return B.Bytevalue ();}}} This is a simple Refactored version of the implementation of PibinaryDigitscalculator. CACHINGDIGITSCALCALCULATOR Package BinaryDigitscalculator The Digitscalculator handle and adds a cache to CalculateBinaryDigit method call. This method improves the readability and maintainability of the code. Users cannot use the BinaryDigitscalculator interface to implement algorithms, so if you need to turn off the cache block, it will be very Easy to implement. In addition, the appropriate test program is easy to write. For example, we write a fake binarydigitscalculator implementation, each time CalculateBinaryDigit is called, gives the same parameters, returns different values. In this way, we can test the cache Work, because if the same value is returned each time, the cache is working properly. This simple implementation is impossible in this test.

转载请注明原文地址:https://www.9cbs.com/read-8740.html

New Post(0)