设计模式——创建型(5种)

310 阅读2分钟

抽(抽象工厂方法模式)工(工厂方法模式)单(单例模式)建(建造者模式)原(原型模式)

抽象工厂方法模式

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。

例子:不同厂家生产不同的电脑

abstract class Computer {
    abstract val name: String
}

class Dell : Computer() {
    override val name = "Dell"
}

class Asus : Computer() {
    override val name = "Asus"
}

class Acer : Computer() {
    override val name = "Acer"
}

class DellFactory : AbstractFactory() {
    override fun produce(): Computer = Dell()
}

class AsusFactory : AbstractFactory() {
    override fun produce(): Computer = Asus()
}

class AcerFactory : AbstractFactory() {
    override fun produce(): Computer = Acer()
}

abstract class AbstractFactory() {
    abstract fun produce(): Computer

    companion object {
        inline operator fun <reified T : Computer> invoke(): AbstractFactory =
            when (T::class) {
                Dell::class -> DellFactory()
                Asus::class -> AsusFactory()
                Acer::class -> AcerFactory()
                else -> throw IllegalArgumentException()
            }
    }
}

fun main() {
    println(AbstractFactory<Dell>().produce().name)
    println(AbstractFactory<Asus>().produce().name)
    println(AbstractFactory<Acer>().produce().name)
}

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory
Method使一个类的实例化延迟到了子类。

例子:同一个厂生产不同的产品

abstract class Factory {
    abstract fun <T : Product> createProduct(cl: Class<T>): Product?
}

abstract class Product {
    abstract fun showInfo()
}

class ConcreateProductA : Product() {
    override fun showInfo() {
        println("I am concreate procuct A")
    }
}

class ConcreateProductB : Product() {
    override fun showInfo() {
        println("I am concreate procuct B")
    }
}

class ConcreateFactory : Factory() {
    override fun <T : Product> createProduct(cl: Class<T>): Product? {
        return Class.forName(cl.name).newInstance() as? T
    }
}

fun main() {
    val factory = ConcreateFactory()
    val productA = factory.createProduct(ConcreateProductA::class.java)
    productA?.showInfo()

    val productB = factory.createProduct(ConcreateProductB::class.java)
    productB?.showInfo()
}

单例模式

确保某一个类只有一个示例,而且自行实例化并向整个系统提供这个实例。

饿汉式

object Singleton1 {
    fun test() {
        println("我是饿汉\n")
    }
}

懒汉式

class Singleton2 private constructor() {
    companion object {
        // 内部使用DCL(Double Check Lock)双重校验锁实现
        val instance: Singleton2 by lazy { Singleton2() }
    }

    fun test() {
        println("我是懒汉")
    }
}

使用

fun main() {
    Singleton1.test()
    Singleton2.instance.test()
}

建造者模式

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

例子:创建一台电脑

class Computer {
    private lateinit var cpu: String
    private lateinit var ram: String
    private var usbCount: Int? = null
    private var keyboard: String? = null
    private var display: String? = null

    companion object {
        fun builder(cpu: String, ram: String): Builder {
            return Builder(cpu, ram)
        }
    }

    override fun toString(): String {
        return "cpu=$cpu\nram=$ram\nusbCount=$usbCount\nkeyboard=$keyboard\ndisplay=$display\n"
    }

    class Builder(cpu: String, ram: String) {
        private val computer = Computer()

        init {
            computer.cpu = cpu
            computer.ram = ram
        }

        fun setUsbCount(usbCount: Int): Builder {
            computer.usbCount = usbCount
            return this
        }

        fun setDisplay(display: String): Builder {
            computer.display = display
            return this
        }

        fun build(): Computer {
            return computer
        }
    }
}

val computer = Computer.builder(cpu = "intel", ram = "1")
    .setDisplay("1")
    .setUsbCount(3)
    .build()

kotlin提供了更简便的方式

// 更简单的方法
data class Computer1(
    var cpu: String,
    var ram: String,
    var usbCount: Int? = null,
    var keyboard: String? = null,
    var display: String? = null
)

val computer1 = Computer1("intel", "1").apply {
    usbCount = 1
}

原型模式

用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。

data class Email(var recipient: String, var subject: String?, var message: String?)

val email = Email("abc@qq.com", "hello", "hahahahha")
val copy = email.copy(recipient = "123@qq.com")

fun main() {
    println("email = $email\n")
    println("copy email = $copy")
}