一、基本概念
定义
定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
核心思想
- 解耦:将对象的创建与使用分离
- 多态:通过子类决定创建什么对象
- 扩展性:增加新产品时无需修改现有代码
二、基本结构
四个核心角色
// 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)
}
}
六、工厂方法模式的优缺点
✅ 优点
- 符合开闭原则:增加新产品时只需添加新的工厂类,无需修改现有代码
- 单一职责原则:创建逻辑集中在工厂类中
- 解耦:客户端代码与具体产品类解耦
- 可扩展性:易于扩展新产品
- 代码可维护性:创建逻辑统一管理
❌ 缺点
- 类数量增加:每增加一个产品就要增加一个工厂类
- 增加系统复杂度:引入了额外的抽象层
- 需要理解工厂层次:客户端需要理解工厂的层次结构
- 可能过度设计:对于简单对象创建,可能过于复杂
七、与相关模式的对比
工厂方法 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)
九、最佳实践指南
何时使用工厂方法模式?
✅ 适用场景:
- 不知道对象的确切类型,需要在运行时决定
- 需要为库或框架提供扩展点
- 需要创建复杂对象,且创建逻辑可能变化
- 需要解耦客户端代码和具体实现类
- 系统中需要经常添加新产品
❌ 避免使用场景:
- 对象创建逻辑简单且固定
- 产品类型很少,且不会扩展
- 性能要求极高,需要避免额外抽象层
- 可以使用依赖注入框架解决创建问题
Android开发建议
-
合理选择工厂类型:
- 简单场景用简单工厂
- 需要扩展用工厂方法
- 创建相关产品族用抽象工厂
-
与依赖注入结合:
// 使用Hilt/Dagger管理工厂
@Module
@InstallIn(SingletonComponent::class)
object FactoryModule {
@Provides
fun provideViewModelFactory(): ViewModelProvider.Factory {
return ViewModelFactory()
}
}
-
考虑使用Kotlin特性:
- 密封类 + 伴生对象工厂方法
- 高阶函数作为工厂
- 内联函数简化泛型工厂
十、总结
工厂方法模式是Android开发中最常用的设计模式之一,特别是在以下场景:
- 框架扩展点:如ViewModelProvider.Factory、FragmentFactory
- UI组件创建:如Adapter中的ViewHolder创建
- 依赖管理:如通过工厂创建带依赖的对象
- 配置管理:如根据配置创建不同实现
关键点:
- 工厂方法模式的核心是让子类决定创建什么对象
- 符合开闭原则,易于扩展
- 在Android中常用于解耦和扩展
- Kotlin提供了更简洁的实现方式
与其他模式的结合:
- 与模板方法模式结合:在父类中定义算法骨架,子类实现工厂方法
- 与抽象工厂模式结合:创建相关产品族
- 与依赖注入结合:通过工厂管理依赖创建
工厂方法模式是构建灵活、可扩展的Android应用的重要工具,合理使用可以显著提高代码的可维护性和可测试性。