Created
August 4, 2018 07:26
-
-
Save LouisShark/d7bad7e8ace032469f198fb5a0bc09c9 to your computer and use it in GitHub Desktop.
Service Locator's imple
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.yibo.housekeeping.test | |
import android.annotation.SuppressLint | |
import android.content.Context | |
import android.support.annotation.NonNull | |
import android.support.annotation.Nullable | |
/** | |
* @author LouisShark | |
* @date 2018/8/4. | |
* this is on com.yibo.housekeeping.test. | |
*/ | |
class Sl private constructor() { | |
interface IService | |
interface Creator<out T> { | |
fun newInstance(@NonNull context: Context): T | |
} | |
companion object { | |
private val sServicesInstances = HashMap<String, Any>() | |
private val sServicesImplementationsMapping = HashMap<String, Class<*>>() | |
@SuppressLint("StaticFieldLeak") | |
private lateinit var mContext: Context | |
private val sServicesInstancesLock = Any() | |
fun init(@NonNull context: Context) { | |
mContext = context.applicationContext | |
} | |
/** | |
* Return instance of desired class or object that implement desired interface. | |
*/ | |
@Suppress("UNCHECKED_CAST") | |
fun <T> get(@NonNull clazz: Class<T>): T { | |
val instance = getService(clazz.name, mContext) | |
return instance as T | |
} | |
/** | |
* This method allows to bind a custom service implementation to an interface. | |
* | |
* @param interfaceClass interface | |
* @param implementationClass class which implement interface specified in first param | |
*/ | |
fun bindCustomServiceImplementation( | |
interfaceClass: Class<*>, | |
implementationClass: Class<*> | |
) { | |
synchronized(sServicesInstancesLock) { | |
sServicesImplementationsMapping.put(interfaceClass.name, implementationClass) | |
} | |
} | |
@NonNull | |
private fun getService(@NonNull name: String, @Nullable applicationContext: Context): Any { | |
synchronized(sServicesInstancesLock) { | |
return sServicesInstances[name] ?: try { | |
val clazz: Class<*> = | |
if (sServicesImplementationsMapping.containsKey(name)) { | |
sServicesImplementationsMapping[name]!! | |
} else { | |
Class.forName(name) | |
} | |
val serviceInstance = try { | |
clazz.getDeclaredConstructor(Context::class.java) | |
.newInstance(applicationContext) | |
} catch (e: NoSuchMethodException) { | |
clazz.getDeclaredConstructor().newInstance() | |
} as? Sl.IService | |
?: throw IllegalArgumentException("Required service must implement IService interface") | |
sServicesInstances[name] = serviceInstance | |
return serviceInstance | |
} catch (e: ClassNotFoundException) { | |
throw IllegalArgumentException( | |
"Requested service class was not found: $name", | |
e | |
) | |
} catch (e: Exception) { | |
throw IllegalArgumentException( | |
"Cannot initialize requested service: $name", | |
e | |
) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment