Teagan Glenn
Teagan42
Senior Software Engineer
Aetna
An abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to procedural programming
A chunk of code that uses, or consumes, another chunk of code is in control of the process, not implementation
Dependencies are provided via constructor arguments
interface ISettingsProvider {
getSetting<SettingType>(settingKey: String): SettingType
}
class TestSettingsProvider : ISettingsProvider {
getSetting<SettingType>(settingKey:String) =
when(settingKey) {
SETTING_IS_PRIVATE -> true
SETTING_ACCOUNT_NAME -> "MyUser"
SettING_SHARE_LOCATION -> false
}
}
class AccountSettingsActivity(val settingsProvider: ISettingsProvider) {
...
fun initialize() =
settingsProvider.run {
username = getSetting<String>(SETTING_ACCOUNT_NAME)
privacy_toggle = getSetting<Boolean>(SETTING_IS_PRIVATE)
share_location = getSettings<Boolean>(SETTING_SHARE_LOCATION)
}
....
}
Dependencies are set via accessors
interface ISettingsProvider {
getSetting<SettingType>(settingKey: String): SettingType
}
class TestSettingsProvider : ISettingsProvider {
getSetting<SettingType>(settingKey:String) =
when(settingKey) {
SETTING_IS_PRIVATE -> true
SETTING_ACCOUNT_NAME -> "MyUser"
SettING_SHARE_LOCATION -> false
}
}
class AccountSettingsActivity() {
var settingsProvider: ISettingsProvider? = null
...
fun initialize() =
settingsProvider?.run {
username = getSetting<String>(SETTING_ACCOUNT_NAME)
privacy_toggle = getSetting<Boolean>(SETTING_IS_PRIVATE)
share_location = getSettings<Boolean>(SETTING_SHARE_LOCATION)
}
....
}
Locates a service, usually by type or name
interface IRESTServiceLocator {
resolve(serviceClass: KClass<IRESTService>): IRestService
}
interface IRetrieveUserService : IRESTService {
...
}
class RetrieveUserService_v1 : IRetrieveUserService {
getCurrentUser(): User?
getUser(userId: Long): User?
}
class UserManager(val serviceLocator: IRESTServiceLocator) {
fun setUsername(username: String) =
serviceLocator.resolve(IRetrieveUserService::class)
.getCurrentUser()
.setUsername(username)
...
}
A framework, of sorts, that can create a given type with all necessary dependencies
class PreferenceWrapper : IPreferenceProvider {
constructor(sharedPreferences: SharedPreferences) {...}
constructor(mockPreferences: MockPreferences) {...}
fun getBoolean(prefName: String): Boolean { ... }
fun getString(prefName: String): String { ... }
}
interface ISingletonScope {
fun getApplicationContext(): Context
fun getPreferences(): IPreferenceProvider
}
class ApplicationContainer(private val context: Context)
: ISingletonScope {
private lateinit var preferences: SharedPreferences
init {
preferences =
PreferenceWrapper(
PreferenceManager.getDefaultSharedPreferences(context))
}
fun getApplicationContext() = context
fun getPreferences() = preferences
}
interface IConfigurationScope {
fun getUserSettings(): UserSettings
fun getPushNotificationSettings(): NotificationSettings
}
class PreferenceConfigurationContainer(private var singletons: ISingletonScope)
: IConfigurationScope {
fun setSingletons(singletonScope: ISingletonScope) {
singletons = singletonScope
}
fun getUserSettings() = with(singletons.getPreferences()) {
UserSettings(getString(PREF_USERNAME), getString(PREF_PASSWORD))
}
fun getPushNotificationSettings() = with(singletons.getPreferences()) {
NotificationSettings(getBoolean(PREF_PUSH_ENABLED),
getBoolean(PREF_PUSH_VIBRATE),
getString(PREF_PUSH_SOUND))
}
}