Java OO design help – how to abstract a save method?
I have a preference class (module) for several different applications Basically, it is the cache of preferences, so the system does not have to call the back end all the time It is similar to caching, but there are some additional details, such as ispreferenceselected, some auxiliary methods, etc
The problem is that I want to include a savepreference in my class so that anyone who uses it can override this method, whether it's a database, a flat file, etc The key is that this module doesn't want to take care of The problem is that it is not an abstract class, so I can't override the static methods. Even if it is, I don't want to create a million instances because I don't want to load preferences every time And I can't create abstract singleton
So I don't know what to do This is the code snippet I want to comment on:
// Please ignore the missing Generics,etc. public class Preference { private static HashMap preferences = new HashMap(); public static ... // Some preferences are objects,such as images,etc. public static setPreference(String name,Object value) { .. some helper code preferences.put(name,value); // ignoring issues with if it already exists ;) savePreference(name,value); // saves to database,flatfile,etc. } }
This is the core class / code used by different systems What I want to do now is to use this class in my code in webapp, desktop application, etc., for example:
public someFunction(...) { .. do some cool code Preference.savePreference("logoImage",image); }
And the savepreference () method not only saves the preferences in memory, but also saves them to an external source Otherwise, I have savepreference () everywhere. I have to trace it through DB calling savepreferencetodb (), a flatfile call, such as savepreferencetoflatfile (), and so on This is very error - prone and someone will forget to save it In addition, it really doesn't make sense to use this type of code to save permanently stored code scattered anywhere, because it should only be executed once Also remember that the main module does not know that the permanent storage is a database, XML file, flat file, etc
Tip: if I execute preference getInstance(). Savepreference(), because you can't abstract a singleton works normally And because it's not possible to override a static method, I can't create a static method savepreference()
The only option I can see is to create some kind of complex factory pattern, but it seems a little too much to me We would therefore appreciate any suggestions
Solution
This sounds like something your dependency injection (DI) container should handle, not a complex factory pattern
In other words, I think you should abandon the Static usage and let other applications create other applications and inject a preference instance into your application If you only use preference as a parameter in the constructor for any other classes that depend on it, you can do this without the di framework
Editor: let me give an example of dependency injection without a framework Take the following courses:
public class Preference { private String userName; public Preference(String userName) { this.userName = userName; } public void savePreference() { // Default implementation saves it to the screen. ;-) System.out.println(userName); } } public class Foo { private Preference p; public Foo(Preference p) { this.p = p; } } public class Bar { private Preference p; public Bar(Preference p) { this.p = p; } } public class Main { public static void main(String[] args) { Preference p = new Preference("Mike"); Foo f = new Foo(p); Bar b = new Bar(p); } }
This is a simple example, but it meets your requirements:
>Preference instance is created only once > the preference class can be extended by anyone who implements the main class to instantiate any type of preference subclass they want if they want to save it in a relational database (or other)
By avoiding static calls first, you can also unit test the somefunction () sample without introducing a potentially large, complex preference framework Instead, someone implemented a mock preference subclass and passed it to the class running somefunction () Your code will be more testable in this way