设计模式——行为型(11种)

405 阅读4分钟

访问者(访问者模式)写好策略(策略模式)备忘录(备忘录模式),观察(观察者模式)模板(模板模式)迭代(迭代器模式)的状态(状态模式),命令(命令模式)中介(中介者模式)解释(解释器模式)责任链(责任链模式

访问者模式

表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。

例子:汽车检查和维修

interface Visitor {
    fun visit(engine: Engine)
    fun visit(wheel: Wheel)
    fun visit(window: Window)
}

interface Visitable {
    fun accept(visitor: Visitor)
}

class Engine : Visitable {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Wheel : Visitable {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Window : Visitable {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class CheckCar : Visitor {
    override fun visit(engine: Engine) {
        println("检查引擎")
    }

    override fun visit(wheel: Wheel) {
        println("检查轮子")
    }

    override fun visit(window: Window) {
        println("检查车窗")
    }
}

class RepairCar : Visitor {
    override fun visit(engine: Engine) {
        println("维修引擎")
    }

    override fun visit(wheel: Wheel) {
        println("维修轮子")
    }

    override fun visit(window: Window) {
        println("维修车窗")
    }
}

class Car {
    private val visits = ArrayList<Visitable>()

    fun addVisit(visitable: Visitable) {
        visits.add(visitable)
    }

    fun show(visitor: Visitor) {
        visits.forEach { it.accept(visitor) }
    }
}

fun main() {
    val car = Car()
    car.addVisit(Engine())
    car.addVisit(Wheel())
    car.addVisit(Window())

    val checkCar = CheckCar()
    car.show(checkCar)

    val repairCar = RepairCar()
    car.show(repairCar)
}

策略模式

定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。

例子:图片加载缓存策略

interface IStrategy {
    fun save(bytes: ByteArray)
}

class DiskStrategy : IStrategy {
    override fun save(bytes: ByteArray) {
        println("使用磁盘缓存")
    }
}

class MemoryStrategy : IStrategy {
    override fun save(bytes: ByteArray) {
        println("使用内存缓存")
    }
}

class ImageLoader {
    private var cacheStrategy: IStrategy = DiskStrategy()

    fun setCacheStrategy(strategy: IStrategy) {
        this.cacheStrategy = strategy
    }

    fun loadImage() {
        cacheStrategy.save(ByteArray(0))
    }
}

fun main() {
    // 使用磁盘缓存
    val loader = ImageLoader()
    loader.loadImage()

    // 使用内存缓存
    loader.setCacheStrategy(MemoryStrategy())
    loader.loadImage()
}

备忘录模式

在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

例子:游戏存档

data class Memento(val progress: Int)
class Caretaker {
    private lateinit var memento: Memento
    fun archive(memento: Memento) {
        // 也可以是其它保存的方式
        println("保存游戏")
        this.memento = memento
    }

    fun getMemento(): Memento = memento
}

class Game {
    private var progress: Int = 0;
    fun play() {
        println("开始游戏,当前进度:$progress")
        progress += 10;
    }

    fun quit() {
        println("退出游戏")
    }

    fun restore(memento: Memento) {
        progress = memento.progress
    }

    fun getMemento(): Memento {
        return Memento(progress)
    }
}

fun main() {
    val game = Game()
    game.play()

    val memento = game.getMemento()
    val taker = Caretaker()
    taker.archive(memento)

    val newGame = Game()
    newGame.restore(taker.getMemento())
    newGame.play()
    newGame.quit()
}

观察者模式

定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。

例子:TextView改变文字内容监听

class TextView {
    interface  ITextChangeListener {
        fun onTextChanged(s:String)
    }

    private val listeners = java.util.ArrayList<ITextChangeListener>()

    var text:String = ""
        set(value) {
            listeners.forEach{
                it.onTextChanged(value)
            }
            field = value
        }

    fun addTextChangedListener(listener: ITextChangeListener){
        listeners.add(listener)
    }
}

class TextChangeListener: TextView.ITextChangeListener {
    override fun onTextChanged(s: String) {
        println("New text is $s")
    }
}

fun main(){
    val textView = TextView()
    textView.addTextChangedListener(TextChangeListener())
    textView.text = "Hello world"
}

模板模式

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

例子:各种车的定义

abstract class Car {
    abstract fun getName(): String
    abstract fun getPrice(): String
    fun introduction() {
        println("车型:${getName()}  价格:${getPrice()}")
    }
}

class Benz : Car() {
    override fun getName(): String {
        return "奔驰"
    }

    override fun getPrice(): String {
        return "100W"
    }
}

class BMW : Car() {
    override fun getName(): String {
        return "宝马"
    }

    override fun getPrice(): String {
        return "80W"
    }
}

class WuLing : Car() {
    override fun getName(): String {
        return "五菱宏光"
    }

    override fun getPrice(): String {
        return "3W"
    }
}

fun main() {
    val cars = ArrayList<Car>()
    cars.add(Benz())
    cars.add(BMW())
    cars.add(WuLing())
    cars.forEach { it.introduction() }
}

迭代器模式

提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。

例子:图书馆书籍

interface Iterator<T> {
    fun next(): T?
    fun hasNext(): Boolean
}

interface Container<T> {
    fun iterator(): Iterator<T>
}

data class Book(val name: String)
class Library : Container<Book> {
    private val books = ArrayList<Book>()

    fun addBook(book: Book) {
        books.add(book)
    }

    override fun iterator(): Iterator<Book> {
        return object : Iterator<Book> {
            private var index: Int = 0
            override fun next(): Book? {
                return if (hasNext()) {
                    books[index].also {
                        index++
                    }
                } else {
                    null
                }
            }

            override fun hasNext(): Boolean {
                return index < books.size
            }
        }
    }
}

fun main() {
    val library = Library()
    library.addBook(Book("Hali波特"))
    library.addBook(Book("Python编程讲解"))
    library.addBook(Book("Java编程讲解"))
    library.addBook(Book("Kotlin开发手册"))
    val iterator = library.iterator()
    while (iterator.hasNext()) {
        println(iterator.next()?.name)
    }
}

状态模式

允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。

例子:手机开关机状态

interface State {
    fun doAction(phone: Phone)
}

class OpenState : State {
    override fun doAction(phone: Phone) {
        println("开机")
        phone.setState(this)
    }
}

class CloseState : State {
    override fun doAction(phone: Phone) {
        println("关机")
        phone.setState(this)
    }
}

class Phone {
    private lateinit var state: State
    fun setState(state: State) {
        this.state = state
    }

    fun getState(): State {
        return state
    }
}

fun main() {
    val phone = Phone()
    val openState = OpenState()
    openState.doAction(phone)
    println("手机当前状态:${phone.getState()}")

    val closeState = CloseState()
    closeState.doAction(phone)
    println("手机当前状态:${phone.getState()}")
}

命令模式

将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。

例子:遥控器上下左右操作

interface Command {
    fun execute()
}

class LeftCommand(private val remoteControl: RemoteControl) : Command {
    override fun execute() {
        remoteControl.toLeft()
    }
}

class UpCommand(private val remoteControl: RemoteControl) : Command {
    override fun execute() {
        remoteControl.toUp()
    }
}

class RightCommand(private val remoteControl: RemoteControl) : Command {
    override fun execute() {
        remoteControl.toRight()
    }
}

class DownCommand(private val remoteControl: RemoteControl) : Command {
    override fun execute() {
        remoteControl.toDown()
    }
}

class Button(
    private val leftCommand: LeftCommand,
    private val rightCommand: RightCommand,
    private val upCommand: UpCommand,
    private val downCommand: DownCommand
) {
    fun toLeft() {
        leftCommand.execute()
    }

    fun toRight() {
        rightCommand.execute()
    }

    fun toUp() {
        upCommand.execute()
    }

    fun toDown() {
        downCommand.execute()
    }
}

class RemoteControl {
    fun toLeft() {
        println("向左")
    }

    fun toUp() {
        println("向上")
    }

    fun toRight() {
        println("向右")
    }

    fun toDown() {
        println("向下")
    }
}

fun main() {
    val remoteControl = RemoteControl()
    val leftCommand = LeftCommand(remoteControl)
    val rightCommand = RightCommand(remoteControl)
    val upCommand = UpCommand(remoteControl)
    val downCommand = DownCommand(remoteControl)

    val button = Button(leftCommand, rightCommand, upCommand, downCommand)
    button.toLeft()
    button.toRight()
    button.toDown()
    button.toUp()
}

中介者模式

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

例子:聊天室

interface Mediator {
    fun sendMessage(from: User, to: User, msg: String)
}

class ChatRoom : Mediator {
    private val users = ArrayList<User>()
    fun addUser(user: User) {
        users.add(user)
    }

    override fun sendMessage(from: User, to: User, msg: String) {
        println("${from.name} 发送消息:$msg")
        users.find { it == to }?.receiveMessage(msg)
    }
}

data class User(val name: String) {
    fun receiveMessage(msg: String) {
        println("$name 收到消息:$msg")
    }
}

fun main() {
    val chatRoom = ChatRoom()
    val user1 = User("DaMing")
    val user2 = User("LiHua")
    chatRoom.addUser(user1)
    chatRoom.addUser(user2)

    chatRoom.sendMessage(user1, user2, "Hello")
    chatRoom.sendMessage(user2, user1, "How are you")
}

解释器模式

给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

例子:输入字符串算数表达式计算结果

abstract class ArithmeticExpression {
    abstract fun interpret(): Int
}

class NumExpression(private val num: Int) : ArithmeticExpression() {
    override fun interpret(): Int {
        return num
    }
}

abstract class OperatorExpression(
    private val exp1: ArithmeticExpression,
    private val exp2: ArithmeticExpression
) : ArithmeticExpression()

class AdditionExpression(
    private val exp1: ArithmeticExpression,
    private val exp2: ArithmeticExpression
) : OperatorExpression(exp1, exp2) {
    override fun interpret(): Int {
        return exp1.interpret() + exp2.interpret()
    }
}

class Calculator(expression: String) {
    private val mExpStack = Stack<ArithmeticExpression>()

    init {
        val elements = expression.split(" ")
        var index = 0
        while (index < elements.size) {
            when (val element = elements[index]) {
                "+" -> {
                    val exp1 = mExpStack.pop()
                    val exp2 = NumExpression(elements[index + 1].toInt())
                    mExpStack.push(AdditionExpression(exp1, exp2))
                    index++
                    if (index + 1 == elements.size - 1) break
                }
                else -> mExpStack.push(NumExpression(element.toInt()))
            }
            index++
        }
    }

    fun calculate(): Int {
        return mExpStack.pop().interpret()
    }
}

fun main() {
    val expression = "1 + 2 + 3 + 4"
    val calculator = Calculator(expression)
    val result = calculator.calculate()
    println("$expression = $result")
}

责任链模式

使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系。

例子:OkHttp发起网络请求的过程

interface Interceptor {
    fun intercept(chain: Chain): Response?
    interface Chain {
        fun request(): Request
        fun proceed(request: Request): Response?
    }
}

data class Response(val result: String)
data class Request(val url: String)

class RealCallChain(
    private val interceptors: ArrayList<Interceptor>,
    private val index: Int,
    private val request: Request
) : Interceptor.Chain {
    private fun copy(index: Int, request: Request): RealCallChain {
        return RealCallChain(interceptors, index, request)
    }

    override fun request(): Request = request
    override fun proceed(request: Request): Response? {
        val next = copy(index + 1, request)
        val interceptor = interceptors[index]
        return interceptor.intercept(next)
    }
}

class NetWorkInterceptor : Interceptor {
    private var isNetWorkConnected = true
    override fun intercept(chain: Interceptor.Chain): Response? {
        println("当前拦截器:NetWorkInterceptor")
        return if (isNetWorkConnected) {
            println("\t网络已连接")
            chain.proceed(chain.request())
        } else {
            println("\t网络未连接")
            null
        }
    }
}

class CacheInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response? {
        println("当前拦截器:CacheInterceptor")
        return chain.proceed(chain.request())
    }
}

class ConnectionInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response? {
        println("当前拦截器:ConnectionInterceptor")
        return chain.proceed(chain.request())
    }
}

class CallServerInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response? {
        println("当前拦截器:CallServerInterceptor")
        println("开始请求网址:${chain.request().url}")
        return Response("Hello world")
    }
}

fun main() {
    val interceptors = ArrayList<Interceptor>()
    interceptors += CacheInterceptor()
    interceptors += ConnectionInterceptor()
    interceptors += NetWorkInterceptor()
    interceptors += CallServerInterceptor()

    val request = Request("https://www.baidu.com")
    val chain = RealCallChain(interceptors, 0, request)
    val response = chain.proceed(request)
    println("response = $response")
}