继上篇文章Kotlin——进阶篇(一):设计模式概述发布后相信你们对设计模式有了一个大概的了解,故而今天为你们讲解最简单的一个设计模式:工厂模式。java
工厂模式分为工厂方法模式和抽象工厂模式,其中,工厂方法模式有一个简易的实现,被称为简单工厂模式,而简单工厂模式也可被称为静态工厂方法模式git
限于篇幅缘由,我会分红三篇文章来说解工厂模式,此篇文章主要讲解简单工厂模式,后续为你们输出工厂方法模式和抽象工厂模式的文章github
总的来讲这不算23
种设计模式中的一种,他实际上是工厂方法模式中的一个简易版。在这里单独做为一篇文章来写,一是为了篇幅考虑,二也是为了能更好的理解及应用工厂方法模式,同时也为下一篇文章作一个启下的做用。设计模式
由于,此模式在新增新产品时会违背开-闭原则。故而这里称其为简单工厂模式,下面看它的定义与做用bash
- 简单工厂模式,又被称为静态工厂方法模式
- 是一种建立型的设计模式
- 定义了一个具体的工厂类来负责建立其余类的实例,被建立的实例一般都具备共同的父类。达到建立者和调用者的分离的目的
简单工厂模式由具体工厂(ConcreteFactory
)、抽象产品(Product
)、具体产品(ConcreteProduct
)三部分构成app
- 具体工厂(
ConcreteFactory
):完成具体产品的建立。- 抽象产品(
Product
):定义了产品的规范,描述了产品的主要特性和功能。- 具体产品(
ConcreteProduct
):实现了抽象产品角色所定义的接口,由具体工厂来建立,它同具体工厂之间一一对应。
UML
图简单工厂模式分为三类:ide
- 普通工厂模式
- 多个工厂方法模式
- 静态工厂方法模式
下面,根据实例为你们讲解各类分类的具体实现及代码:函数
例: 此实例来至《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:实现工厂类,这里根据上面的三种分类来定义,请继续往下看,讲述各个分类的特色以及上面实例的编写
结合上面的代码写出普通工厂模式的工厂类代码
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
结构判断.为了解决这些问题,引入多个工厂方法模式。优化一下代码!
结合上面的代码写出多个工厂方法模式的工厂类代码
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
复制代码
分析
从上面的代码能够看出,解决了一部分普通工厂模式的弊端。每次使用的时候仍是须要实例化工厂。故而要解决这个问题,引入下面的静态工厂方法模式。这也是简单工厂模式的最好实现,推荐此写法
结合上面的代码写出静态工厂方法模式的工厂类代码
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
复制代码
咱们知道一个简单工厂模式,包含了一个工厂角色、一个抽象产品角色以及一个具体的角色。当出现下面三种状况时,具体简单工厂模式的写法。
当一个系统过于简单,只有一个具体产品角色时,此时不须要抽象产品角色。咱们先看一个图:
实现
步骤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()
}
复制代码
在某些状况下,工厂角色能够由抽象产品角色扮演,即抽象产品角色同时是其子类的工厂,最具体的表现为系统中的DateFormat
类。看下面的图:
这里就不举例说明了,有兴趣的能够去看看DateForamt
类及其子类的实现。
当抽象产品角色被省略时,工厂角色能够和具体产品角色合并。换言之,就是一个产品类就是自身的工厂。看下面的图:
具体的代码为:
class ConcreteProduce{
companion object{
fun createProduce() : ConcreteProduce{
return ConcreteProduce()
}
}
fun show(){
println("show函数被调用了")
}
}
复制代码
测试:
fun main(){
val produce = ConcreteProduce.createProduce()
produce.show()
}
复制代码
优势
- 该模式的核心在与工厂类,这个类能够决定何时建立哪个具体产品的实例子。
- 客户端能够直接免除直接建立产品对象的责任,而只负责消费产品。简单工厂模式经过这种方式实现了对责任的分离。
缺点
- 因为工厂类集中了全部产品建立逻辑,一旦不能正常工做,整个系统都要受到影响。
- 使用简单工厂模式将会增长系统中类的个数,在必定程序上增长了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,一样破坏了“开闭原则”;在产品类型较多时,有可能形成工厂逻辑过于复杂,不利于系统的扩展和维护。
- 简单工厂模式因为使用了静态工厂方法,形成工厂角色没法造成基于继承的等级结构。
适用场景
工厂类负责建立的对象比较少:因为建立的对象较少,不会形成工厂方法中的业务逻辑太过复杂。
以上就是所有关于简单工厂模式的知识点。请掌握它的结构组成以及优缺点,而且当结构组成部分可缺省或可合并时,也能判断出该代码是简单工厂模式结构。
若是各位大佬看了以后感受还阔以,就请各位大佬随便star
一下,您的关注是我最大的动力。
个人我的博客:Jetictors
个人github:Jetictors