Android 工厂方法模式浅析

10 阅读8分钟

一、基本概念

定义

定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

核心思想

  1. 解耦:将对象的创建与使用分离
  2. 多态:通过子类决定创建什么对象
  3. 扩展性:增加新产品时无需修改现有代码

二、基本结构

四个核心角色

// 1. Product (产品接口)
interface Vehicle {
    fun drive(): String
    fun getFuelType(): String
}

// 2. ConcreteProduct (具体产品)
class Car : Vehicle {
    override fun drive(): String = "驾驶汽车"
    override fun getFuelType(): String = "汽油"
    
    fun playMusic() {
        println("播放音乐")
    }
}

class Motorcycle : Vehicle {
    override fun drive(): String = "骑摩托车"
    override fun getFuelType(): String = "汽油"
    
    fun wheelie() {
        println("翘头特技")
    }
}

class ElectricCar : Vehicle {
    override fun drive(): String = "驾驶电动汽车"
    override fun getFuelType(): String = "电力"
    
    fun autoPilot() {
        println("自动驾驶模式")
    }
}

// 3. Creator (创建者抽象类/接口)
abstract class VehicleFactory {
    // 工厂方法
    abstract fun createVehicle(): Vehicle
    
    // 模板方法 - 可以使用工厂方法
    fun testDrive(): String {
        val vehicle = createVehicle()
        return "试驾开始: ${vehicle.drive()}, 燃料类型: ${vehicle.getFuelType()}"
    }
}

// 4. ConcreteCreator (具体创建者)
class CarFactory : VehicleFactory() {
    override fun createVehicle(): Vehicle {
        println("生产一辆汽车...")
        return Car()
    }
}

class MotorcycleFactory : VehicleFactory() {
    override fun createVehicle(): Vehicle {
        println("生产一辆摩托车...")
        return Motorcycle()
    }
}

class ElectricCarFactory : VehicleFactory() {
    override fun createVehicle(): Vehicle {
        println("生产一辆电动汽车...")
        return ElectricCar()
    }
}

三、Android中的工厂方法模式

1. Fragment工厂方法

// 在Activity中使用工厂方法创建Fragment
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 根据条件使用不同的工厂
        val factory: FragmentFactory = if (isPremiumUser()) {
            PremiumFragmentFactory()
        } else {
            FreeFragmentFactory()
        }
        
        val fragment = factory.createFragment()
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit()
    }
    
    // 工厂接口
    interface FragmentFactory {
        fun createFragment(): Fragment
    }
    
    // 具体工厂
    class FreeFragmentFactory : FragmentFactory {
        override fun createFragment(): Fragment {
            return FreeVersionFragment()
        }
    }
    
    class PremiumFragmentFactory : FragmentFactory {
        override fun createFragment(): Fragment {
            return PremiumVersionFragment()
        }
    }
    
    // 具体产品
    class FreeVersionFragment : Fragment() {
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_free, container, false)
        }
    }
    
    class PremiumVersionFragment : Fragment() {
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_premium, container, false)
        }
    }
}

2. Adapter工厂方法

// 多类型RecyclerView Adapter中的工厂方法
class MultiTypeAdapter(private val items: List<AdapterItem>) : 
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
    // 工厂接口
    interface ViewHolderFactory {
        fun createViewHolder(parent: ViewGroup): RecyclerView.ViewHolder
        fun getViewType(): Int
    }
    
    // 具体工厂
    class TextViewHolderFactory : ViewHolderFactory {
        override fun createViewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_text, parent, false)
            return TextViewHolder(view)
        }
        
        override fun getViewType(): Int = ViewType.TEXT.ordinal
    }
    
    class ImageViewHolderFactory : ViewHolderFactory {
        override fun createViewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_image, parent, false)
            return ImageViewHolder(view)
        }
        
        override fun getViewType(): Int = ViewType.IMAGE.ordinal
    }
    
    // 工厂管理器
    private val factoryMap = mapOf<Int, ViewHolderFactory>(
        ViewType.TEXT.ordinal to TextViewHolderFactory(),
        ViewType.IMAGE.ordinal to ImageViewHolderFactory()
    )
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return factoryMap[viewType]?.createViewHolder(parent)
            ?: throw IllegalArgumentException("未知的viewType: $viewType")
    }
    
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = items[position]
        when (holder) {
            is TextViewHolder -> holder.bind(item as TextItem)
            is ImageViewHolder -> holder.bind(item as ImageItem)
        }
    }
    
    override fun getItemViewType(position: Int): Int {
        return items[position].viewType.ordinal
    }
    
    override fun getItemCount(): Int = items.size
    
    enum class ViewType { TEXT, IMAGE }
    
    sealed class AdapterItem(val viewType: ViewType)
    data class TextItem(val text: String) : AdapterItem(ViewType.TEXT)
    data class ImageItem(val imageUrl: String) : AdapterItem(ViewType.IMAGE)
    
    class TextViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        private val textView: TextView = view.findViewById(R.id.textView)
        
        fun bind(item: TextItem) {
            textView.text = item.text
        }
    }
    
    class ImageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        private val imageView: ImageView = view.findViewById(R.id.imageView)
        
        fun bind(item: ImageItem) {
            // 加载图片
            Glide.with(imageView.context)
                .load(item.imageUrl)
                .into(imageView)
        }
    }
}

3. ViewModel工厂方法

// ViewModelProvider.Factory 是工厂方法模式的典型应用
class CustomViewModelFactory(
    private val userId: String,
    private val repository: UserRepository
) : ViewModelProvider.Factory {
    
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
            return UserViewModel(userId, repository) as T
        }
        throw IllegalArgumentException("未知的ViewModel类: ${modelClass.name}")
    }
}

// 在Activity中使用
class UserActivity : AppCompatActivity() {
    private lateinit var viewModel: UserViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val userId = intent.getStringExtra(EXTRA_USER_ID) ?: ""
        val repository = (application as MyApp).userRepository
        
        val factory = CustomViewModelFactory(userId, repository)
        viewModel = ViewModelProvider(this, factory)[UserViewModel::class.java]
        
        viewModel.user.observe(this) { user ->
            // 更新UI
        }
    }
}

四、工厂方法模式的变体

1. 简单工厂(静态工厂方法)

// 注意:这不是标准的工厂方法模式,但很常用
class VehicleFactory {
    companion object {
        // 静态工厂方法
        fun createVehicle(type: VehicleType): Vehicle {
            return when (type) {
                VehicleType.CAR -> Car()
                VehicleType.MOTORCYCLE -> Motorcycle()
                VehicleType.ELECTRIC_CAR -> ElectricCar()
                VehicleType.TRUCK -> Truck()
            }
        }
        
        // 根据参数创建不同对象
        fun createVehicleFromConfig(config: VehicleConfig): Vehicle {
            return when {
                config.isElectric -> ElectricCar()
                config.passengerCount > 2 -> Car()
                config.isTwoWheeler -> Motorcycle()
                else -> Truck()
            }
        }
    }
}

enum class VehicleType { CAR, MOTORCYCLE, ELECTRIC_CAR, TRUCK }

data class VehicleConfig(
    val isElectric: Boolean,
    val passengerCount: Int,
    val isTwoWheeler: Boolean
)

2. 参数化工厂方法

abstract class DialogFactory {
    abstract fun createDialog(context: Context, type: DialogType): Dialog
    
    fun showDialog(context: Context, type: DialogType) {
        val dialog = createDialog(context, type)
        dialog.show()
    }
}

class MaterialDialogFactory : DialogFactory() {
    override fun createDialog(context: Context, type: DialogType): Dialog {
        return when (type) {
            DialogType.ALERT -> MaterialAlertDialogBuilder(context)
                .setTitle("提示")
                .setMessage("这是一个警告对话框")
                .setPositiveButton("确定", null)
                .create()
            
            DialogType.CONFIRMATION -> MaterialAlertDialogBuilder(context)
                .setTitle("确认")
                .setMessage("确定要执行此操作吗?")
                .setPositiveButton("确定", null)
                .setNegativeButton("取消", null)
                .create()
            
            DialogType.PROGRESS -> MaterialAlertDialogBuilder(context)
                .setTitle("请稍候")
                .setMessage("正在加载...")
                .setCancelable(false)
                .create()
        }
    }
}

enum class DialogType { ALERT, CONFIRMATION, PROGRESS }

3. 依赖注入中的工厂方法

// 使用Dagger/Hilt实现工厂方法
@Module
@InstallIn(ActivityComponent::class)
object ViewModelModule {
    
    @Provides
    fun provideUserViewModelFactory(
        userRepository: UserRepository
    ): ViewModelProvider.Factory {
        return object : ViewModelProvider.Factory {
            @Suppress("UNCHECKED_CAST")
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
                    return UserViewModel(userRepository) as T
                }
                throw IllegalArgumentException("未知的ViewModel类")
            }
        }
    }
}

// 在Activity中使用
@AndroidEntryPoint
class UserActivity : AppCompatActivity() {
    
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    
    private val viewModel: UserViewModel by viewModels { viewModelFactory }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        viewModel.users.observe(this) { users ->
            // 更新UI
        }
    }
}

五、Android开发中的实际应用

1. 网络请求工厂

interface ApiServiceFactory {
    fun createService(baseUrl: String): ApiService
    fun createAuthService(token: String): AuthApiService
    fun createUploadService(): UploadApiService
}

class RetrofitApiServiceFactory(private val context: Context) : ApiServiceFactory {
    
    private val retrofitCache = mutableMapOf<String, Retrofit>()
    
    override fun createService(baseUrl: String): ApiService {
        val retrofit = getOrCreateRetrofit(baseUrl)
        return retrofit.create(ApiService::class.java)
    }
    
    override fun createAuthService(token: String): AuthApiService {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(createOkHttpClientWithAuth(token))
            .build()
        
        return retrofit.create(AuthApiService::class.java)
    }
    
    override fun createUploadService(): UploadApiService {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://upload.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(createOkHttpClientForUpload())
            .build()
        
        return retrofit.create(UploadApiService::class.java)
    }
    
    private fun getOrCreateRetrofit(baseUrl: String): Retrofit {
        return retrofitCache[baseUrl] ?: Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .client(createDefaultOkHttpClient())
            .build().also {
                retrofitCache[baseUrl] = it
            }
    }
    
    private fun createDefaultOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .addInterceptor(LoggingInterceptor())
            .build()
    }
    
    private fun createOkHttpClientWithAuth(token: String): OkHttpClient {
        return createDefaultOkHttpClient().newBuilder()
            .addInterceptor(AuthInterceptor(token))
            .build()
    }
    
    private fun createOkHttpClientForUpload(): OkHttpClient {
        return createDefaultOkHttpClient().newBuilder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .build()
    }
}

2. 数据库DAO工厂

interface DatabaseFactory {
    fun createUserDao(): UserDao
    fun createProductDao(): ProductDao
    fun createOrderDao(): OrderDao
    fun createTransactionDao(): TransactionDao
}

class RoomDatabaseFactory(private val context: Context) : DatabaseFactory {
    
    private val database: AppDatabase by lazy {
        Room.databaseBuilder(
            context.applicationContext,
            AppDatabase::class.java,
            "app_database.db"
        ).build()
    }
    
    override fun createUserDao(): UserDao = database.userDao()
    
    override fun createProductDao(): ProductDao = database.productDao()
    
    override fun createOrderDao(): OrderDao = database.orderDao()
    
    override fun createTransactionDao(): TransactionDao = database.transactionDao()
}

// 使用依赖注入
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
    
    @Provides
    @Singleton
    fun provideDatabaseFactory(context: Context): DatabaseFactory {
        return RoomDatabaseFactory(context)
    }
    
    @Provides
    fun provideUserDao(factory: DatabaseFactory): UserDao {
        return factory.createUserDao()
    }
    
    @Provides
    fun provideProductDao(factory: DatabaseFactory): ProductDao {
        return factory.createProductDao()
    }
}

3. 主题工厂

interface ThemeFactory {
    fun createButton(context: Context): Button
    fun createTextView(context: Context): TextView
    fun createEditText(context: Context): EditText
    fun createCardView(context: Context): CardView
}

class LightThemeFactory : ThemeFactory {
    override fun createButton(context: Context): Button {
        return Button(context).apply {
            setBackgroundColor(ContextCompat.getColor(context, R.color.light_primary))
            setTextColor(ContextCompat.getColor(context, R.color.light_on_primary))
        }
    }
    
    override fun createTextView(context: Context): TextView {
        return TextView(context).apply {
            setTextColor(ContextCompat.getColor(context, R.color.light_text_primary))
        }
    }
    
    override fun createEditText(context: Context): EditText {
        return EditText(context).apply {
            setBackgroundResource(R.drawable.light_edittext_background)
            setTextColor(ContextCompat.getColor(context, R.color.light_text_primary))
        }
    }
    
    override fun createCardView(context: Context): CardView {
        return CardView(context).apply {
            setCardBackgroundColor(ContextCompat.getColor(context, R.color.light_surface))
            cardElevation = 4f
        }
    }
}

class DarkThemeFactory : ThemeFactory {
    override fun createButton(context: Context): Button {
        return Button(context).apply {
            setBackgroundColor(ContextCompat.getColor(context, R.color.dark_primary))
            setTextColor(ContextCompat.getColor(context, R.color.dark_on_primary))
        }
    }
    
    override fun createTextView(context: Context): TextView {
        return TextView(context).apply {
            setTextColor(ContextCompat.getColor(context, R.color.dark_text_primary))
        }
    }
    
    override fun createEditText(context: Context): EditText {
        return EditText(context).apply {
            setBackgroundResource(R.drawable.dark_edittext_background)
            setTextColor(ContextCompat.getColor(context, R.color.dark_text_primary))
        }
    }
    
    override fun createCardView(context: Context): CardView {
        return CardView(context).apply {
            setCardBackgroundColor(ContextCompat.getColor(context, R.color.dark_surface))
            cardElevation = 4f
        }
    }
}

// 在Activity中使用
class ThemeActivity : AppCompatActivity() {
    
    private lateinit var themeFactory: ThemeFactory
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 根据设置选择主题工厂
        themeFactory = if (isDarkThemeEnabled()) {
            DarkThemeFactory()
        } else {
            LightThemeFactory()
        }
        
        setContentView(R.layout.activity_theme)
        
        // 动态创建视图
        val button = themeFactory.createButton(this)
        val textView = themeFactory.createTextView(this)
        
        // 添加到布局
        val container = findViewById<ViewGroup>(R.id.container)
        container.addView(button)
        container.addView(textView)
    }
}

六、工厂方法模式的优缺点

✅ 优点

  1. 符合开闭原则:增加新产品时只需添加新的工厂类,无需修改现有代码
  2. 单一职责原则:创建逻辑集中在工厂类中
  3. 解耦:客户端代码与具体产品类解耦
  4. 可扩展性:易于扩展新产品
  5. 代码可维护性:创建逻辑统一管理

❌ 缺点

  1. 类数量增加:每增加一个产品就要增加一个工厂类
  2. 增加系统复杂度:引入了额外的抽象层
  3. 需要理解工厂层次:客户端需要理解工厂的层次结构
  4. 可能过度设计:对于简单对象创建,可能过于复杂

七、与相关模式的对比

工厂方法 vs 抽象工厂

// 工厂方法:一个工厂类只创建一个产品
interface ButtonFactory {
    fun createButton(): Button  // 只有一个产品
}

// 抽象工厂:一个工厂类创建多个相关产品
interface ThemeFactory {
    fun createButton(): Button      // 多个相关产品
    fun createTextView(): TextView
    fun createDialog(): Dialog
}

工厂方法 vs 简单工厂

// 简单工厂:一个工厂类根据参数创建不同产品
class SimpleVehicleFactory {
    fun createVehicle(type: String): Vehicle {
        return when (type) {
            "car" -> Car()
            "bike" -> Bike()
            else -> throw IllegalArgumentException()
        }
    }
}

// 工厂方法:每个产品有对应的工厂类
interface VehicleFactory {
    fun createVehicle(): Vehicle
}

class CarFactory : VehicleFactory {
    override fun createVehicle() = Car()
}

class BikeFactory : VehicleFactory {
    override fun createVehicle() = Bike()
}

八、Kotlin中的优化实现

1. 使用高阶函数作为工厂

// 将工厂方法定义为函数类型
typealias ViewFactory = (Context) -> View

// 工厂映射表
val viewFactories = mapOf<String, ViewFactory>(
    "button" to { context -> 
        Button(context).apply {
            text = "动态按钮"
        }
    },
    "textView" to { context ->
        TextView(context).apply {
            text = "动态文本"
            textSize = 16f
        }
    },
    "editText" to { context ->
        EditText(context).apply {
            hint = "请输入..."
        }
    }
)

// 使用
fun createView(type: String, context: Context): View? {
    return viewFactories[type]?.invoke(context)
}

2. 使用伴生对象工厂方法

sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
    object Loading : Result<Nothing>()
    
    // 伴生对象中的工厂方法
    companion object {
        fun <T> success(data: T): Result<T> = Success(data)
        fun error(exception: Throwable): Result<Nothing> = Error(exception)
        fun loading(): Result<Nothing> = Loading
    }
}

// 使用
val result1 = Result.success("数据")
val result2 = Result.error(RuntimeException("错误"))
val result3 = Result.loading()

3. 使用内联函数和reified类型

// 泛型工厂方法
inline fun <reified T : View> createView(context: Context): T {
    return when (T::class) {
        Button::class -> Button(context) as T
        TextView::class -> TextView(context) as T
        EditText::class -> EditText(context) as T
        else -> throw IllegalArgumentException("不支持的View类型")
    }
}

// 使用
val button: Button = createView(context)
val textView: TextView = createView(context)

九、最佳实践指南

何时使用工厂方法模式?

✅ 适用场景

  1. 不知道对象的确切类型,需要在运行时决定
  2. 需要为库或框架提供扩展点
  3. 需要创建复杂对象,且创建逻辑可能变化
  4. 需要解耦客户端代码和具体实现类
  5. 系统中需要经常添加新产品

❌ 避免使用场景

  1. 对象创建逻辑简单且固定
  2. 产品类型很少,且不会扩展
  3. 性能要求极高,需要避免额外抽象层
  4. 可以使用依赖注入框架解决创建问题

Android开发建议

  1. 合理选择工厂类型

    • 简单场景用简单工厂
    • 需要扩展用工厂方法
    • 创建相关产品族用抽象工厂
  2. 与依赖注入结合

// 使用Hilt/Dagger管理工厂
@Module
@InstallIn(SingletonComponent::class)
object FactoryModule {
    @Provides
    fun provideViewModelFactory(): ViewModelProvider.Factory {
        return ViewModelFactory()
    }
}
  1. 考虑使用Kotlin特性

    • 密封类 + 伴生对象工厂方法
    • 高阶函数作为工厂
    • 内联函数简化泛型工厂

十、总结

工厂方法模式是Android开发中最常用的设计模式之一,特别是在以下场景:

  1. 框架扩展点:如ViewModelProvider.Factory、FragmentFactory
  2. UI组件创建:如Adapter中的ViewHolder创建
  3. 依赖管理:如通过工厂创建带依赖的对象
  4. 配置管理:如根据配置创建不同实现

关键点

  • 工厂方法模式的核心是让子类决定创建什么对象
  • 符合开闭原则,易于扩展
  • 在Android中常用于解耦和扩展
  • Kotlin提供了更简洁的实现方式

与其他模式的结合

  • 模板方法模式结合:在父类中定义算法骨架,子类实现工厂方法
  • 抽象工厂模式结合:创建相关产品族
  • 依赖注入结合:通过工厂管理依赖创建

工厂方法模式是构建灵活、可扩展的Android应用的重要工具,合理使用可以显著提高代码的可维护性和可测试性。