实用精短-kotlin设计模式

30 篇文章 0 订阅
28 篇文章 0 订阅

分享:
kotlin学习练习网站-https://github.com/dbacinski/Design-Patterns-In-Kotlin
kotlin资料网站-
设计模式网站-http://www.runoob.com/design-pattern/decorator-pattern.html
引言:
设计模式的本质是让我们更好的运用面向对象有点,应对项目的后期的需求变更和变化
那么在学习和使用kotlin中结合以往的设计模式会怎么样呢?
以下不是抛开实际需求而是实战中运用到设计模式

主页目录:
策略模式
单例模式
工厂模式
代理模式
观察者模式
建造者模式
适配器模式
责任链模式
命令解释器模式
装饰模式
外观模式
状态模式
过滤器模式
访问者模式

策略模式Strategy

功能:为不同的字符串处理提供不同的算法

import java.text.DecimalFormat
import java.util.regex.Pattern

interface ValueTransform {
    @Throws(NumberFormatException::class)
    fun transform(str:String?):String?
}

inline fun String.vt(t:ValueTransform): String?{
    return t.transform(this)
}

class NumberFromat(val len:Int):ValueTransform{
    override fun transform(str: String?): String? {
        return String.format("%0${len}d",Integer.valueOf(str))
    }
}
class TimerNumberFromat(val len:Int):ValueTransform{
    override fun transform(str: String?): String? {
        var sb=StringBuffer();
        val pattern = Pattern.compile("[\\d]++|[\\D]++")
        val matcher = pattern.matcher(str)
        fun isNumber(str: String):Boolean=Pattern.compile("[0-9]*").matcher(str).matches()
        while (matcher.find()) {
           var value=matcher.group()
           when(isNumber(value)){
               true -> sb.append(value.vt(NumberFromat(2)))
               else -> sb.append(value)
           }
        }
        return sb.toString()
    }
}
class GoldFormat(val len:Int):ValueTransform{
    override fun transform(str: String?): String? {
        var sb=StringBuffer(".")
        if(len<=0)
        {
            return str?.toDouble()?.toInt().toString()
        }
        for(i in 0..len-1) {
            sb.append("0")
        }
        return DecimalFormat(sb.toString()).format(str?.toDouble())
    }

}
fun main(args: Array<String>) {
    println("9->"+("9".vt(NumberFromat(2))))
    println("9->"+("9".vt(GoldFormat(2))))
    println("1989-9-1 1:4:15->"+("1989-9-1 1:4:15".vt(TimerNumberFromat(2))));
}
单例模式Singleton

object PrinterDriver {
    init {
        println("Initializing with object: $this")
    }

    fun print() = println("Printing with object: $this")
}

fun main(args: Array<String>) {
    println("Start")
    PrinterDriver.print()
    PrinterDriver.print()
}
工厂模式Factory

功能:减少项目变化所造成的影响

/**抽象工厂*/
interface Plant

class OrangePlant : Plant

class ApplePlant : Plant

abstract class PlantFactory {
    abstract fun makePlant(): Plant

    companion object {
        inline fun <reified T : Plant> createFactory(): PlantFactory = when (T::class) {
            OrangePlant::class -> OrangeFactory()
            ApplePlant::class  -> AppleFactory()
            else               -> throw IllegalArgumentException() as Throwable
        }
    }
}

class AppleFactory : PlantFactory() {
    override fun makePlant(): Plant = ApplePlant()
}

class OrangeFactory : PlantFactory() {
    override fun makePlant(): Plant = OrangePlant()
}

fun main(args: Array<String>) {
    val plantFactory = PlantFactory.createFactory<OrangePlant>()
    val plant = plantFactory.makePlant()
    println("Created plant: $plant")
}
代理模式ProtectionProxy

功能:通过代理禁止访问文件的密码

interface File {
    fun read(name: String)
}

class NormalFile : File {
    override fun read(name: String) = println("Reading file: $name")
}

//Proxy:
class SecuredFile : File {
    val normalFile = NormalFile()
    var password: String = ""

    override fun read(name: String) {
        if (password == "secret") {
            println("Password is correct: $password")
            normalFile.read(name)
        } else {
            println("Incorrect password. Access denied!")
        }
    }
}

fun main(args: Array<String>) {
    val securedFile = SecuredFile()
    securedFile.read("readme.md")

    securedFile.password = "secret"
    securedFile.read("readme.md")
}
观察者模式Observer

功能:文本框内容变化时通知其他监听器发生变化

import kotlin.properties.Delegates

interface TextChangedListener {
    fun onTextChanged(newText: String)
}

class PrintingTextChangedListener : TextChangedListener {
    override fun onTextChanged(newText: String) = println("Text is changed to: $newText")
}

class TextView {

    var listener: TextChangedListener? = null

    var text: String by Delegates.observable("") { prop, old, new ->
        listener?.onTextChanged(new)
    }
}

fun main(args: Array<String>) {
    val textView = TextView()
    textView.listener = PrintingTextChangedListener()
    textView.text = "Lorem ipsum"
    textView.text = "dolor sit amet"
}
建造者模式Build

功能:创建一个可自定义各种样式的对话框

import java.io.File

// Let's assume that Dialog class is provided by external library.
// We have only access to Dialog public interface which cannot be changed.
/**建造*/
class Dialog() {

    fun showTitle() = println("showing title")

    fun setTitle(text: String) = println("setting title text $text")

    fun setTitleColor(color: String) = println("setting title color $color")

    fun showMessage() = println("showing message")

    fun setMessage(text: String) = println("setting message $text")

    fun setMessageColor(color: String) = println("setting message color $color")

    fun showImage(bitmapBytes: ByteArray) = println("showing image with size ${bitmapBytes.size}")

    fun show() = println("showing dialog $this")
}

//Builder:
class DialogBuilder() {
    constructor(init: DialogBuilder.() -> Unit) : this() {
        init()
    }

    private var titleHolder: TextView? = null
    private var messageHolder: TextView? = null
    private var imageHolder: File? = null

    fun title(init: TextView.() -> Unit) {
        titleHolder = TextView().apply { init() }
    }

    fun message(init: TextView.() -> Unit) {
        messageHolder = TextView().apply { init() }
    }

    fun image(init: () -> File) {
        imageHolder = init()
    }

    fun build(): Dialog {
        val dialog = Dialog()

        titleHolder?.apply {
            dialog.setTitle(text)
            dialog.setTitleColor(color)
            dialog.showTitle()
        }

        messageHolder?.apply {
            dialog.setMessage(text)
            dialog.setMessageColor(color)
            dialog.showMessage()
        }

        imageHolder?.apply {
            dialog.showImage(readBytes())
        }

        return dialog
    }

    class TextView {
        var text: String = ""
        var color: String = "#00000"
    }
}

//Function that creates dialog builder and builds Dialog
fun dialog(init: DialogBuilder.() -> Unit): Dialog {
    return DialogBuilder(init).build()
}

fun main(args: Array<String>) {

    val dialog: Dialog = dialog {
        title {
            text = "Dialog Title"
        }
        message {
            text = "Dialog Message"
            color = "#333333"
        }
        image {

            File.createTempFile("image", "jpg")
        }
    }

    dialog.show()
}
适配器模式Adapter

/**适配器模式器模式-将开氏温度和摄氏温度换算*/
interface Temperature {
    var temperature: Double
}

class CelsiusTemperature(override var temperature: Double) : Temperature

class FahrenheitTemperature(var celsiusTemperature: CelsiusTemperature) : Temperature {

    override var temperature: Double
        get() = convertCelsiusToFahrenheit(celsiusTemperature.temperature)
        set(temperatureInF) {
            celsiusTemperature.temperature = convertFahrenheitToCelsius(temperatureInF)
        }

    private fun convertFahrenheitToCelsius(f: Double): Double = (f - 32) * 5 / 9

    private fun convertCelsiusToFahrenheit(c: Double): Double = (c * 9 / 5) + 32
}

fun main(args: Array<String>) {
    val celsiusTemperature = CelsiusTemperature(0.0)
    val fahrenheitTemperature = FahrenheitTemperature(celsiusTemperature)

    celsiusTemperature.temperature = 36.6
    println("${celsiusTemperature.temperature} C -> ${fahrenheitTemperature.temperature} F")

    fahrenheitTemperature.temperature = 100.0
    println("${fahrenheitTemperature.temperature} F -> ${celsiusTemperature.temperature} C")
}
责任链模式ChainOfResponsibility

功能:根据url来定义(跳转 打开或者自定义)功能 类似击鼓传花
enum class SchemeAction(var host: String, var action: (Map<String, String>) -> Unit) {
    OrderUI("scheme://order", {
        println("start order acitvity - parm=${it["id"]}")
    }),
    Evaluate("scheme://evaluate", {
        println("start evaluate acitvity ${it["id"]}")
    }),
    web("", {
        println("start web")
    });

    fun isMatching(url: String): SchemeAction? = when (true) {
        url.indexOf(host) == 0 -> this
        else -> null;
    }

    companion object {
        fun matching(url: String) {
            SchemeAction.values().forEach {
                var scheme = it.isMatching(url)
                scheme?.action?.invoke(paramToMap(url))
                scheme?.run { return }
            }
        }

        fun paramToMap(url: String): Map<String, String> = HashMap<String, String>().apply {
             var arr=url.split("\\?".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
             if(arr.size==2){
                 arr[1].split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray().forEach {
                     var parm=it.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                     if(parm.size==2)this[parm[0]]=parm[1]
                }
            }
        }
    }


}
fun main(args: Array<String>) {
    SchemeAction.matching("scheme://evaluate?id=5")
    SchemeAction.matching("http://www.baidu.com")
}
命令解释器模式CommandandInterpreterPattern

功能:给产品或者其他设计定义一种开放简单脚本用来编写剧情

import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock

class TimeWait(val time: Long) : Runnable {
    companion object {
        val poolExecutor: ScheduledThreadPoolExecutor = ScheduledThreadPoolExecutor(10)
    }
    var keepOn = false;
    var lock = ReentrantLock()
    var condition = lock.newCondition()
    override fun run() {
        println("等待:" + time)
        poolExecutor.schedule({
            lock.lock()
            keepOn = true
            condition.signalAll();
            lock.unlock()
        }, time, TimeUnit.MILLISECONDS)
        while (!keepOn) {
            lock.lock()
            condition.await()
            lock.unlock()
        }
    }
}
interface Interpreter {
    fun interpreter(command: String, commandArr: List<String>): Runnable?
}

class SkillInterpreter : Interpreter {
    override fun interpreter(command: String, arr: List<String>): Runnable? {
        if (arr[0].equals("skill")) {
            return when (arr[2]) {
                "eat" -> Runnable { println("${arr[1]} skill ${arr[2]} (O ^ ~ ^ O)") }
                "ultimate" -> Runnable { println("${arr[1]} skill ${arr[2]}(╯‵□′)╯︵┴─┴") }
                else -> Runnable { }
            }
        }
        return null
    }
}

class MoveInterpreter : Interpreter {
    override fun interpreter(command: String, arr: List<String>): Runnable? {
        if (arr[0].equals("move")) {
            return when (arr[3]) {
                "right" -> Runnable { println("${arr[1]} is >>move>>  ${arr[2]}") }
                "left" -> Runnable { println("${arr[1]} is <<move<<  ${arr[2]}") }
                else -> Runnable { }
            }
        }
        return null
    }
}

class TimeInterpreter : Interpreter {
    override fun interpreter(command: String, arr: List<String>): Runnable? {
        if (arr[0].equals("wait")) {
            return TimeWait(arr[1].toLong())
        }
        return null
    }
}

object ScriptProcessor {
    var service = Executors.newSingleThreadExecutor();
    var queueAction = LinkedList<Runnable>()
    var scripts= arrayListOf<Interpreter>()
    fun load(clazz:Class<out Interpreter>):ScriptProcessor{
        scripts.add(clazz.newInstance())
        return this
    }

    fun addAction(actuin: String): ScriptProcessor = apply {
        addAction(change(actuin))
    }
    fun addAction(actuin: Runnable): ScriptProcessor = apply { queueAction.add(actuin) }
    private fun change(action: String): Runnable {
        try {
            var arr = action.split(" ")
            for(script in scripts) {script.interpreter(action, arr)?.apply{ return this }}
            return Runnable { println("无效脚本:${action}") }
        } catch (e: Exception) {
            return Runnable { println("错误脚本:${action}") }
        }
    }


    fun start(): ScriptProcessor = apply {
        while (!queueAction.isEmpty()) {
            service.submit(queueAction.pollFirst())
        }
    }
}

fun main(args: Array<String>) {
    ScriptProcessor
            .load(SkillInterpreter::class.java)
            .load(MoveInterpreter::class.java)
            .load(TimeInterpreter::class.java)
            .addAction("skill k eat")
            .addAction("wait 2000")
            .addAction("wait ^%$%#$%")
            .addAction("move k 5 right")
            .addAction("wait 2500")
            .addAction("mov k 5 left")//<-错误脚本
            .addAction("wait 1000")
            .addAction("move k 5 left")
            .addAction("wait 1000")
            .addAction("skill k ultimate")
            .start()
}
输入结果
等待:2000
错误脚本:wait ^%%
k is >>move>> 5
等待:2500
无效脚本:mov k 5 left
等待:1000
k is <<move<< 5
等待:1000
k skill ultimate(╯‵□′)╯︵┴─┴
装饰者模式Decirator

功能:用类的方式创建html标签
类似的例子比如文字有颜色有粗体有斜体
饮料有冰 热 加糖 加椰果等等需求
这种需要大量组合的类

open class TextBlock
{
    constructor(){}
    constructor(str:String){content=str}
    constructor(block:TextBlock)
    {
        nextBlock=block
    }
    var content: String?=null
    var nextBlock:TextBlock?=null
    open fun outPrintln():String{
        return content?:"";
    }
    open fun link(textBlock: TextBlock):TextBlock{
        textBlock.nextBlock=this
        return textBlock
    }
}
class ColorTextBlock:TextBlock
{
    constructor(color:String){}
    constructor(color:String,block:TextBlock){nextBlock=block}

    override fun outPrintln():String{
        return "<font color='#FF0000'>${nextBlock?.outPrintln()}</font>";
    }
}
class StrongTextBlock:TextBlock
{
    constructor(){}
    constructor(block:TextBlock){nextBlock=block}

    override fun outPrintln():String{
        return "<strong>${nextBlock?.outPrintln()?:""}</strong>";
    }
}

class SmallTextBlock:TextBlock
{
    constructor(){}
    constructor(block:TextBlock){nextBlock=block}

    override fun outPrintln():String{
        return "<small>${nextBlock?.outPrintln()}</small>";
    }
}


fun main(args: Array<String>) {
    ColorTextBlock("#FF0000",SmallTextBlock(TextBlock("文字"))).run { outPrintln() }
    //简写
    TextBlock("文字")
            .link(SmallTextBlock())
            .link(StrongTextBlock())
            .link(ColorTextBlock("#FF0000"))
            .run { outPrintln() }
}
外观模式Facade

功能:包装一层,将原本不同的很复杂的接口(支付宝sdk和微信sdk)统一成一种

import SimplePay.SimplePayListen
import SimplePay.pay
import java.util.*

class AliPaySdk{
  interface AliPayListen{
      fun alipayStatusListn(code:Int)
  }
  fun pay(gold:String,listen:AliPayListen){
      listen.alipayStatusListn(0)
  }
}
class WeixinPaySdk{
    interface WeixinPayListen{
        fun alipayStatusListn(errCode:String)
    }
    fun pay(gold:String,listen:WeixinPayListen){
        listen.alipayStatusListn("susscess")
    }
}
object SimplePay
{
    const val PAY_TYPE_ALI=1
    const val PAY_TYPE_WEIXIN=2

    var aliPay=AliPaySdk()
    var weixinPay=WeixinPaySdk();

    interface SimplePayListen{
        fun alipayStatusListn(payType:Int,errorCode:Int,message:String)
    }
    fun pay(payType:Int,gold:Double,listen:SimplePayListen){
        when(payType){
            PAY_TYPE_ALI->{
                AliPaySdk().pay(gold.toString(),object:AliPaySdk.AliPayListen{
                    override fun alipayStatusListn(code: Int) {
                        var message:String=when(code)
                        {
                            0->"成功"
                            else->"失败"
                        }
                        listen.alipayStatusListn(PAY_TYPE_ALI,code,message)
                    }

                })
            }
            PAY_TYPE_WEIXIN->{
                WeixinPaySdk().pay(gold.toString(),object:WeixinPaySdk.WeixinPayListen{
                    override fun alipayStatusListn(errCode: String) {
                        var code=0
                        var message:String=when(errCode)
                        {
                            "susscess"->{"成功"}
                            else->{code=2;"失败"}
                        }
                        listen.alipayStatusListn(PAY_TYPE_ALI,code,message)
                    }

                })

            }
            else->{
                throw RuntimeException("no pay method")
            }
        }
    }

}
fun main(args: Array<String>) {
    SimplePay.pay(SimplePay.PAY_TYPE_ALI,1.0, object:SimplePayListen{
        override fun alipayStatusListn(payType: Int, errorCode: Int, message: String) {
            println("error code:${errorCode}  message:${message}")
        }
    })
}
状态模式模式State

功能:为每一种状态定义不同的显示和点击事件

class Order{
    var subscribeState:State = State(1,{println("ui->subscribeState")},{println("onclick->subscribeState")})
    var payState:State = State(2,{println("show state->payState") },{println("onclick->payState") })
    var finishState:State = State(3,{ println("show state->finishState")},{ println("onclick->finishState") })
    var status:State=subscribeState

    inner class State(val status:Int,val onRefreshUI:()->Unit,val onClick:()->Unit)
    fun refreshUI(){
       println("refreshUI")
       status.onRefreshUI.invoke()
   }
   fun onClick(){
       println("onClick")
       status.onClick.invoke()
   }
}


fun main(arr:Array<String>){
    var order=Order()
    order.status=order.finishState
    order.refreshUI()
    order.onClick()
}
过滤器模式Filter

为不同的人群筛选复杂的贷款套餐业务

import java.util.*

inline fun <reified T> orFilter(vararg args: (t:T)->Boolean): (t:T)->Boolean = { t: T->
    var isCheck = false;
    args.forEach { isCheck =  it.invoke(t)||isCheck }
    isCheck
}
inline fun <reified T> andFilter(vararg args: (t:T)->Boolean): (t:T)->Boolean = {t: T->
    var isCheck = true;
    args.forEach { isCheck =   it.invoke(t)&&isCheck}
    isCheck
}


inline fun <reified T> filter(list: List<T>, vararg arr:(t:T)->Boolean): List<T> {
    var iterator = list.listIterator()
    var resultList = arrayListOf<T>()

    while (iterator.hasNext()) {
        var value = iterator.next()
        var isCheck = true;
        for (filter in arr) {
            isCheck = filter.invoke(value)
            if (!isCheck) {
                break
            }
        }
        if (isCheck) {
            resultList.add(value)
        }
    }
    return resultList
}



data class Person(val id: Int, val name: String, val sex: Int, val loan: Int)

var manFilter = {t:Person->t.sex == 1}
var womenFilter = {t:Person->t.sex == 2}
var loan5Filter = {t:Person->t.loan>=5}
var loan6Filter = {t:Person->t.loan>=6}
var idFilter = {t:Person->t.id<=5}

//查询前5幸运客户或者资金大于5的男性
var planA=orFilter(andFilter(manFilter, loan5Filter), idFilter)
//查询资金大于等于5并且是男性 或者资金大于等于6的女性
var planB=andFilter(orFilter(manFilter, loan5Filter), orFilter(womenFilter, loan6Filter))

fun main(args: Array<String>) {
    var arr = arrayListOf<Person>()
    for (i in 1..10) {
        var person = Person(i, "张" + i, 1 + Random().nextInt(2), (Random().nextInt(10)));
        arr.add(person)
    }
    arr.forEach{
        println(it)
    }
    println("=====planA=======")
    filter(arr, planA).forEach {
        println(it)
    }
    println("=====planB=======")
    // println("=====Lambda======")
    filter(arr, planB).forEach {
        println(it)
    }
    println("==planA and planB==")
    filter(arr,planA,planB).forEach {
        println(it)
    }

}
输入结果
Person(id=1, name=张1, sex=1, loan=5)
Person(id=2, name=张2, sex=1, loan=3)
Person(id=3, name=张3, sex=1, loan=6)
Person(id=4, name=张4, sex=2, loan=2)
Person(id=5, name=张5, sex=1, loan=7)
Person(id=6, name=张6, sex=2, loan=8)
Person(id=7, name=张7, sex=1, loan=4)
Person(id=8, name=张8, sex=1, loan=8)
Person(id=9, name=张9, sex=1, loan=1)
Person(id=10, name=张10, sex=2, loan=7)
=====planA=======
Person(id=1, name=张1, sex=1, loan=5)
Person(id=2, name=张2, sex=1, loan=3)
Person(id=3, name=张3, sex=1, loan=6)
Person(id=4, name=张4, sex=2, loan=2)
Person(id=5, name=张5, sex=1, loan=7)
Person(id=8, name=张8, sex=1, loan=8)
=====planB=======
Person(id=3, name=张3, sex=1, loan=6)
Person(id=5, name=张5, sex=1, loan=7)
Person(id=6, name=张6, sex=2, loan=8)
Person(id=8, name=张8, sex=1, loan=8)
Person(id=10, name=张10, sex=2, loan=7)
==planA and planB==
Person(id=3, name=张3, sex=1, loan=6)
Person(id=5, name=张5, sex=1, loan=7)
Person(id=8, name=张8, sex=1, loan=8)
访问者模式Visitor

功能:打印遍历当前文件夹下 mp3 或者 图片文件

import java.io.File
import java.io.FileFilter
import java.util.ArrayList


class MP3FileFilter : FileFilter {
    override fun accept(file:java.io.File?): Boolean {
        fun checkFileName():Boolean{ val name = file?.getName();
            return name!!.endsWith(".mp3") || name!!.endsWith(".mp4")
        }
        return when(true)
        {
            file?.isDirectory->false
            checkFileName()->true
            else->false
        }
    }
}
class ImgFileFilter : FileFilter {
    override fun accept(file:java.io.File?): Boolean {
        fun checkFileName():Boolean{ val name = file?.getName();
            return name!!.endsWith(".jpeg") || name!!.endsWith(".png")
        }
        return when(true)
        {
            file?.isDirectory->false
            checkFileName()->true
            else->false
        }
    }
}

fun getAllFile(baseFile: java.io.File,filter:FileFilter): List<java.io.File> = ArrayList<java.io.File>().apply {
    if (baseFile.isFile() || !baseFile.exists()) {
        return this
    }
    val files = baseFile.listFiles()
    for (file in files) {
        if (file.isDirectory()) {
            getAllFile(file,filter)
        } else {
            if(filter.accept(file)) {
                this.add(file)
            }
        }
    }

}

fun main(args: Array<String>) {
    println(getAllFile(java.io.File("."),MP3FileFilter()));
    println(getAllFile(java.io.File("."),ImgFileFilter()));
}
输入结果
[]
[]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值