设计模式——结构型(7种)

948 阅读2分钟

带(代理模式)上适(适配器模式)当的装(装饰模式)备组(组合模式)合可以让外(外观模式)国侨(桥接模式)胞享(享元模式)受(游戏)

代理模式

为其他对象提供一种代理以控制对这个对象的访问,分为静态代理和动态代理。

  • 静态代理
/** 实现1 **/
interface IGamePlayer {
    fun rank()
    fun upgrade()
}

// 被委托者
class RealGamePlayer : IGamePlayer {
    override fun rank() {
        println("打排位\n")
    }

    override fun upgrade() {
        println("升级\n")
    }
}

// 委托者
class DelegateGamePlayer1(player:IGamePlayer) : IGamePlayer by player

/** 实现2 **/
class DelegateGamePlayer2(): IGamePlayer {
    private val delegateGaemPlayer = RealGamePlayer()

    override fun rank() {
        delegateGaemPlayer.rank()
    }

    override fun upgrade() {
        delegateGaemPlayer.upgrade()
    }
}


fun main(){
    println("代理模式1")
    val realGamePlayer = RealGamePlayer()
    val delegateGamePlayer1 = DelegateGamePlayer1(realGamePlayer)
    delegateGamePlayer1.rank()
    delegateGamePlayer1.upgrade()

    println("代理模式2")
    val delegateGamePlayer2 = DelegateGamePlayer2()
    delegateGamePlayer2.rank()
    delegateGamePlayer2.upgrade()
}
  • 动态代理
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

interface IGamePlayer {
    fun rank()
    fun upgrade()
}

// 被委托者
class RealGamePlayer : IGamePlayer {
    override fun rank() {
        println("打排位\n")
    }

    override fun upgrade() {
        println("升级\n")
    }
}

class GamePlayerHandler(private val target: Any?) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
        println("method ${method?.name}")
        return method?.invoke(target, *(args ?: arrayOfNulls<Any>(0)))
    }
}

fun main() {
    val obj = RealGamePlayer()
    val player = Proxy.newProxyInstance(obj::class.java.classLoader,
            obj::class.java.interfaces, GamePlayerHandler(obj)) as IGamePlayer
    player.rank()
    player.upgrade()
}

适配器模式

将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。

/**
 * 适配器模式
 *
 * 适配器模式的三个特点:
 *      1、 适配器对象实现原有接口
 *      2、 适配器对象组合一个实现新接口的对象(这个对象也可以不实现一个接口,只是一个单纯的对象)
 *      3、 对适配器原有接口方法的调用被委托给新接口的实例的特定方法
 *
 * 场景:国标(国内标准)插座为3个孔,德标准(德国标准)插座为2个孔
 * 问题:一国内游客去德国旅游,拿着国标的充电器(3个孔)如何使用德标的插孔(2个孔)
 * 解决办法:电源转化适配器
 */


interface GBSocketInterface{
    // 三孔插头充电
    fun powerWithThreeFlat()
}

class GBSocket:GBSocketInterface{
    override fun powerWithThreeFlat() {
        println("国标:使用三孔插头充电")
    }
}

interface DBSocketInterface{
    // 两孔插头充电
    fun powerWithTwoFlat()
}

class DBSocket:DBSocketInterface{
    override fun powerWithTwoFlat() {
        println("德标:使用两孔插头充电")
    }
}

// 德国宾馆
class DHotel(private val dbSocket:DBSocketInterface){
    // 充电
    fun charge(){
        dbSocket?.powerWithTwoFlat()
    }
}

// 适配器
class SocketAdapter(private val gbSocket: GBSocketInterface):DBSocketInterface{
    override fun powerWithTwoFlat() {
        gbSocket.powerWithThreeFlat()
    }
}

val gbSocket = GBSocket()
val adapter = SocketAdapter(gbSocket)
val hotel = DHotel(adapter)
hotel.charge()

装饰器模式

动态扩展类的功能

class Text(val text: String) {
    fun draw() = print("$text")
}

/** 动态扩展类的功能 */
fun Text.underline(decorated: Text.() -> Unit) {
    print("_")
    this.decorated()
    print("_")
}

fun Text.background(decorated: Text.() -> Unit) {
    print("\u001B[43m")
    this.decorated()
    print("\u001B[0m")
}

fun preDecorated(decorated: Text.() -> Unit): Text.() -> Unit {
    return { background { underline { decorated() } } }
}

val text = preDecorated {
    Text("hello").draw()
}

组合模式

将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。 

interface AbstractFile {
    var childCount: Int
    fun getChild(i: Int): AbstractFile
    fun size(): Long
}

class File(val size: Long, override var childCount: Int = 0) : AbstractFile {
    override fun getChild(i: Int): AbstractFile {
        throw RuntimeException("You shouldn't call the method in File")
    }

    override fun size() = size
}

class Folder(override var childCount: Int) : AbstractFile {
    override fun getChild(i: Int): AbstractFile {
        return File(100)
    }

    override fun size(): Long = (0 until childCount).map { getChild(it).size() }.sum()
}

val folder = Folder(10)
print("size = ${folder.size()}")

外观模式

为一个复杂的子系统提供一个简化的统一接口

class ComplexSystemStore(val filePath: String) {
    init {
        println("reading data from filr $filePath\n")
    }

    val store = HashMap<String, String>()

    fun store(key: String, payload: String) {
        store.put(key, payload)
    }

    fun read(key: String) = store[key] ?: ""

    fun commit() = println("storing cached data: $store to file $filePath\n")
}

data class User(val login: String)

// 外观
class UserRepository {
    val systemPreference = ComplexSystemStore("/data/default.prefs")

    fun save(user: User) {
        systemPreference.store("USER_KEY", user.login)
        systemPreference.commit()
    }

    fun findFirst() = User(systemPreference.read("USER_KEY"))
}

val repository = UserRepository()
val user = User("hellokit")
repository.save(user)
val resultUser = repository.findFirst()
print(resultUser)

桥接模式

将抽象部分与它的实现部分相分离,使他们可以独立的变化。

abstract class Shape() {
    abstract fun draw()
}


class Circle(val color: Color) : Shape() {
    override fun draw() {
        println("I am circle color is ${color.name()}\n")
    }
}

class Square(val color: Color) : Shape() {
    override fun draw() {
        print("I am square color is ${color.name()}\n")
    }
}

abstract class Color() {
    abstract fun name(): String
}

class Red() : Color() {
    override fun name() = "red"
}

class Blue : Color() {
    override fun name() = "blue"
}

class Yellow : Color() {
    override fun name() = "yellow"
}

val red = Red()
val blue = Blue()
val circle = Circle(red)
val square = Square(blue)
circle.draw()
square.draw()

享元模式

系统中存在大量的相似对象,或者需要缓冲池的场景,亦或是细粒度的对象都具备相似的外部状态,而且内部状态与环境无关的场景。

import java.util.*

interface BottleCap {
    // 瓶盖颜色
    val color:String
    // 二维码信息
    fun disQRContent(qeContent: QRContent): String
}

class QRContent {
    private lateinit var mQRContent: String
    private lateinit var mUUid: String

    init {
        mUUid = UUID.randomUUID().toString()
    }

    fun setmQRContent(mQRContent: String) {
        this.mQRContent = mQRContent
    }

    fun getmQRContent(): String {
        mQRContent = "二维码唯一ID:$mUUid\n根据ID得到中奖信息${Random().nextInt(6) + 1}等奖"
        return mQRContent
    }

}

class ConcreteBottleCap(override val color: String) : BottleCap {

    override fun disQRContent(qeContent: QRContent): String {
        return "瓶盖颜色${color}\n二维码内容${qeContent.getmQRContent()}"
    }
}

class BottleWeightFactory {
    companion object {
        val map = HashMap<String, BottleCap>()

        fun getBottleCap(color: String): BottleCap {
            if (map.get(color) != null) {
                return map[color] as BottleCap
            } else {
                val cfw = ConcreteBottleCap(color)
                map.put(color, cfw)
                return cfw
            }
        }
    }
}

val bottleCap1 = BottleWeightFactory.getBottleCap("蓝色")
val bottleCap2 = BottleWeightFactory.getBottleCap("蓝色")

print("bottleCap1 获奖结果=${bottleCap1.disQRContent(QRContent())}\n")
print("bottleCap2 获奖结果=${bottleCap2.disQRContent(QRContent())}\n")