Pendant le développement, une fonction de mise en cache des données est nécessaire. Par exemple, un formulaire doit remplir le nom d'utilisateur, les informations de la carte d'identité, l'âge, etc.
Première étape:
Mise en cache directement avec sp
Problème : aucune conception, beaucoup de code écrit, aucune extension
Note : Le principe de SharedPreferences est également d'exploiter les fichiers. Enregistrez-les au format XML. Faites attention à la soumission du commit.
Deuxième étape :
Écrivez-le dans une classe d'outils PreferencesUtils, puis initialisez-le dans Application
PreferencesUtils.getInstance().init(this);
- Approche singleton de l'objet PreferencesUtils
- Utiliser des appels chaînés pour définir des données spécifiques
public class PreferencesUtils {
private volatile static PreferencesUtils mInstance;
private SharedPreferences mPreferences;
private SharedPreferences.Editor mEditor;
private PreferencesUtils(){
}
public void init(Context context){
mPreferences = context.getApplicationContext().getSharedPreferences("cache",Context.MODE_PRIVATE);
mEditor = mPreferences.edit();
}
public static PreferencesUtils getInstance(){
if(mInstance == null){
synchronized (PreferencesUtils.class){
if(mInstance == null){
mInstance = new PreferencesUtils();
}
}
}
return mInstance;
}
public PreferencesUtils saveString(String key,String value){
mEditor.putString(key,value);
return this;
}
public void commit(){
mEditor.commit();
}
public String getString(String key){
return mPreferences.getString(key,"");
}
}
Problème : Il est impossible de vider une partie du cache et il est impossible de combiner le cache mémoire avec le cache disque ou le cache de base de données.
Troisième étape :
Utiliser un modèle d'usine simple
1. Définir la spécification IOHandler pour le stockage des données
public interface IOHandler {
void save(String key,String value);
String getString(String key);
}
2. Définissez des classes de cache spécifiques, telles que : cache mémoire, cache SP
// 内存缓存
public class MemoryIOHandler implements IOHandler {
// 存在运行内存里面 内部原理:LinkedHashMap
private static LruCache<String, Object> mCache = new LruCache<>(10 * 1024 * 1024);
@Override
public void save(String key, String value) {
mCache.put(key, value);
}
@Override
public String getString(String key) {
return (String) mCache.get(key);
}
}
// SP缓存
public class SpIOHandler implements IOHandler{
@Override
public void save(String key, String value) {
PreferencesUtils.getInstance().saveString(key,value);
}
@Override
public String getString(String key) {
return PreferencesUtils.getInstance().getString(key);
}
}
3. Définir la classe d'usine
public class IOHandlerFactory {
public enum IOType{
MEMORY,PREFERENCES
}
public static IOHandler createIOHandler(IOType ioType){
switch (ioType){
case MEMORY:
return new MemoryIOHandler();
case PREFERENCES:
return new SpIOHandler();
default:
return null;
}
}
}
Question : Si vous devez ajouter une nouvelle méthode de mise en cache, vous devez ajouter un type et modifier la classe d'usine.
Quatrième étape :
En utilisant le modèle de méthode d'usine, chaque usine correspond à un produit et l'usine est appelée en externe à l'aide de produits spécifiques.
Un IOFactory correspond à un IOHandler
1.IOHandler reste inchangé
2. Créez une interface d'usine
public interface IOFactory {
IOHandler createIOHandler();
}
3. Créez une usine spécifique
Ne produisez qu'un seul produit. Si vous devez ajouter un nouveau type, il vous suffit de créer un produit et d'ajouter la méthode du produit.
public class MemoryIOFactory implements IOFactory{
@Override
public IOHandler createIOHandler() {
return new MemoryIOHandler();
}
}
public class SpIOFactory implements IOFactory{
@Override
public IOHandler createIOHandler() {
return new PreferencesIOHandler();
}
}
4. Appels externes
IOFactory ioFactory = new MemoryIOFactory();
IOHandler ioHandler = ioFactory.createIOHandler();
Problème : avec l'expansion des fonctions, les classes d'usine continuent d'augmenter et la logique de base est la même, ce qui entraîne un code redondant.
Cinquième étape :
modèle d'usine abstrait
1.IOHandler reste inchangé
2. Définissez IOFactory et utilisez une classe générique
public interface IOFactory {
IOHandler createIOHandler(Class<? extends IOHandler> ioHandlerClass);
}
3. Utilisez un singleton pour créer une fabrique abstraite, IOHandlerFactory
public class IOHandlerFactory implements IOFactory {
private static volatile IOHandlerFactory mInstance;
private IOHandler mMemoryIOHandler,mSpIOHandler;
private IOHandlerFactory(){
}
public static IOHandlerFactory getInstance(){
if(mInstance == null){
synchronized (IOHandlerFactory.class){
if(mInstance == null){
mInstance = new IOHandlerFactory();
}
}
}
return mInstance;
}
public IOHandler createIOHandler(Class<? extends IOHandler> ioHandlerClass){
try {
return ioHandlerClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return new PreferencesIOHandler();
}
public IOHandler getMemoryIOHandler(){
if(mMemoryIOHandler == null){
mMemoryIOHandler = createIOHandler(MemoryIOHandler.class);
}
return mMemoryIOHandler;
}
public IOHandler getDiskIOHandler(){
return createIOHandler(DiskIOHandler.class);
}
public IOHandler getSpIOHandler(){
if(mPreferencesIOHandler == null){
mSpIOHandler = createIOHandler(SpIOHandler.class);
}
return mPreferencesIOHandler;
}
public IOHandler getDefaultIOHandler(){
return getMemoryIOHandler();
}
}
4. Appels externes
IOHandler ioHandler = IOHandlerFactory.getInstance().getDefaultIOHandler();
scènes à utiliser :
Il y a des points communs, mais il peut y avoir de la diversité plus tard : il est nécessaire de cacher les détails complexes de la création et d'encapsuler l'instanciation et la création d'objets.
Par exemple:
Utilisation d'une base de données, d'une bibliothèque de chargement d'images, d'une bibliothèque de chargement réseau, etc. S'il existe un nouveau framework ultérieurement et que vous souhaitez le remplacer, vous pouvez utiliser le mode usine pour le créer et remplacer les fonctions d'origine avec des modifications minimes.