Kotlin——进阶篇(二): 简单工厂模式详解

继上篇文章Kotlin——进阶篇(一):设计模式概述发布后相信你们对设计模式有了一个大概的了解,故而今天为你们讲解最简单的一个设计模式:工厂模式java

工厂模式分为工厂方法模式抽象工厂模式,其中,工厂方法模式有一个简易的实现,被称为简单工厂模式,而简单工厂模式也可被称为静态工厂方法模式git

限于篇幅缘由,我会分红三篇文章来说解工厂模式,此篇文章主要讲解简单工厂模式,后续为你们输出工厂方法模式和抽象工厂模式的文章github

目录

1、定义与做用

总的来讲这不算23种设计模式中的一种,他实际上是工厂方法模式中的一个简易版。在这里单独做为一篇文章来写,一是为了篇幅考虑,二也是为了能更好的理解及应用工厂方法模式,同时也为下一篇文章作一个启下的做用。设计模式

由于,此模式在新增新产品时会违背开-闭原则。故而这里称其为简单工厂模式,下面看它的定义与做用bash

1.一、定义与做用

  • 简单工厂模式,又被称为静态工厂方法模式
  • 是一种建立型的设计模式
  • 定义了一个具体的工厂类来负责建立其余类的实例,被建立的实例一般都具备共同的父类。达到建立者和调用者的分离的目的

1.二、结构说明

简单工厂模式由具体工厂(ConcreteFactory)、抽象产品(Product)、具体产品(ConcreteProduct)三部分构成app

  • 具体说明

  1. 具体工厂(ConcreteFactory):完成具体产品的建立。
  2. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  3. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来建立,它同具体工厂之间一一对应。
  • UML

2、分类与实例

简单工厂模式分为三类:ide

  1. 普通工厂模式
  2. 多个工厂方法模式
  3. 静态工厂方法模式

下面,根据实例为你们讲解各类分类的具体实现及代码:函数

: 此实例来至《Java与模式》书中,固然作了一部分修改post

现有三种水果(苹果(Apple)、香蕉(Banana)、葡萄(Grape),它们都有着价格(price)属性以及生长(grow)、收获(harvest)方法。其中苹果有一个颜色(color)属性。葡萄有一个有籽或无籽属性(seed)。现有一园丁,根据需求去采摘水果。测试

实现

步骤1:给三种水果定义一个抽象角色(IFruit),其中抽象角色能够是接口或抽象类

interface IFruit{

   /**
    * 生长
    */
   fun grow()

   /**
    * 收获
    */
   fun harvest()

   /**
    * 价格
    */
   var price : Double
   
}
复制代码

步骤2:定义各个具体角色。

/ 定义苹果类
class Apple(private val color : String, override var price: Double) : IFruit{

   override fun grow() {
       println("grow apple...")
   }

   override fun harvest() {
       println("harvest apple ...")
       println("I`m apple, color : $color \t price : $price")
   }
   
}

// 定义香蕉类
class Banana(override var price: Double) : IFruit{

   override fun grow() {
       println("grow banana...")
   }

   override fun harvest() {
       println("harvest banana ...")
       println("I`m banana, price : $price")
   }

}

// 定义葡萄类
class Grape(private val seed : Boolean, override var price: Double) : IFruit{

   override fun grow() {
       println("grow grape...")
   }

   override fun harvest() {
       println("harvest grape ...")
       println("I`m grape, seed : $seed \t price : $price")
   }
   
}
复制代码

步骤3:实现工厂类,这里根据上面的三种分类来定义,请继续往下看,讲述各个分类的特色以及上面实例的编写

2.一、普通工厂模式

结合上面的代码写出普通工厂模式的工厂类代码

class FirstFruitFactory{

    /**
     * 根据类型建立
     */
    fun createFactory(type : String) : IFruit?{
        return when(type){
            "apple" -> Apple("red", 12.8)
            "banana" -> Banana(8.8)
            "grape" -> Grape(false, 15.98)
            else -> null
        }
    }

}
复制代码

测试类:

fun main(args : Array<String>){
    val firstFruit = FirstFruitFactory().createFactory("apple")
    firstFruit?.harvest()
}
复制代码

输出结果为:

harvest apple ...
I`m apple, color : red 	 price : 12.8
复制代码

分析

  • 当传入的参数不知足建立具体产品类时,返回null对象或者可抛出异常。
  • 并且包含了稍显复杂的if-else结构判断.
  • 每次使用都需实例化工厂

为了解决这些问题,引入多个工厂方法模式。优化一下代码!

2.二、多个工厂方法模式

结合上面的代码写出多个工厂方法模式的工厂类代码

class SecondFruitFactory{

    /**
     * 建立苹果
     */
    fun createApple() : IFruit{
        return Apple("green", 8.8)
    }

    /**
     * 建立香蕉
     */
    fun createBanana() : IFruit{
        return Banana(5.5)
    }

    /**
     * 建立葡萄
     */
    fun createGrape() : IFruit{
        return Grape(true, 12.8)
    }

}
复制代码

测试:

fun main(args : Array<String>){
    // 多个工厂方法测试
    val secondFruit = SecondFruitFactory().createBanana()
    secondFruit.harvest()
}
复制代码

输出结果为:

harvest banana ...
I`m banana, price : 5.5
复制代码

分析

从上面的代码能够看出,解决了一部分普通工厂模式的弊端。每次使用的时候仍是须要实例化工厂。故而要解决这个问题,引入下面的静态工厂方法模式。这也是简单工厂模式的最好实现,推荐此写法

2.三、静态工厂方法模式

结合上面的代码写出静态工厂方法模式的工厂类代码

class ThirdFruitFactory{

    companion object{
        /**
         * 建立苹果
         */
        fun createApple() : IFruit{
            return Apple("green", 8.8)
        }

        /**
         * 建立香蕉
         */
        fun createBanana() : IFruit{
            return Banana(5.5)
        }

        /**
         * 建立葡萄
         */
        fun createGrape() : IFruit{
            return Grape(true, 12.8)
        }
    }
}
复制代码

测试:

fun main(args : Array<String>){
    // 静态工厂方法测试
    val thirdFruit = ThirdFruitFactory.createGrape()
    thirdFruit.harvest()
}
复制代码

输出结果为:

harvest grape ...
I`m grape, seed : true 	 price : 12.8
复制代码

3、合并

咱们知道一个简单工厂模式,包含了一个工厂角色、一个抽象产品角色以及一个具体的角色。当出现下面三种状况时,具体简单工厂模式的写法。

3.一、缺省抽象角色

当一个系统过于简单,只有一个具体产品角色时,此时不须要抽象产品角色。咱们先看一个图:

实现

步骤1:建立具体的产品角色

class ConcreteProduce{
    
    fun show(){
        println("show函数被调用")
    }
    
}
复制代码

步骤2:建立工厂类

class ConcreteFactory{
    
    companion object{
        fun factory : ConcreteProduce{
            return ConcreteProduce()
        }
    }
    
}
复制代码

测试:

fun main(args : Array<String>){
    val produce = ConcreteFactory.factory()
    produce.show()
}
复制代码

3.二、抽象产品角色和工厂角色合并

在某些状况下,工厂角色能够由抽象产品角色扮演,即抽象产品角色同时是其子类的工厂,最具体的表现为系统中的DateFormat类。看下面的图:

这里就不举例说明了,有兴趣的能够去看看DateForamt类及其子类的实现。

3.三、三者皆合并

当抽象产品角色被省略时,工厂角色能够和具体产品角色合并。换言之,就是一个产品类就是自身的工厂。看下面的图:

具体的代码为:

class ConcreteProduce{

    companion object{
        fun createProduce() : ConcreteProduce{
            return ConcreteProduce()
        }
    }
    
    fun show(){
        println("show函数被调用了")
    }
}
复制代码

测试:

fun main(){
    val produce = ConcreteProduce.createProduce()
    produce.show()
}
复制代码

4、简单工厂模式的优缺点

  • 优势

    1. 该模式的核心在与工厂类,这个类能够决定何时建立哪个具体产品的实例子。
    2. 客户端能够直接免除直接建立产品对象的责任,而只负责消费产品。简单工厂模式经过这种方式实现了对责任的分离。
  • 缺点

    1. 因为工厂类集中了全部产品建立逻辑,一旦不能正常工做,整个系统都要受到影响。
    2. 使用简单工厂模式将会增长系统中类的个数,在必定程序上增长了系统的复杂度和理解难度。
    3. 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,一样破坏了“开闭原则”;在产品类型较多时,有可能形成工厂逻辑过于复杂,不利于系统的扩展和维护。
    4. 简单工厂模式因为使用了静态工厂方法,形成工厂角色没法造成基于继承的等级结构。
  • 适用场景

    工厂类负责建立的对象比较少:因为建立的对象较少,不会形成工厂方法中的业务逻辑太过复杂。

总结

以上就是所有关于简单工厂模式的知识点。请掌握它的结构组成以及优缺点,而且当结构组成部分可缺省或可合并时,也能判断出该代码是简单工厂模式结构。

项目源代码

若是各位大佬看了以后感受还阔以,就请各位大佬随便star一下,您的关注是我最大的动力。
个人我的博客Jetictors
个人githubJetictors

欢迎各位大佬进群共同研究、探索

QQ群号:497071402

相关文章
相关标签/搜索