一周两个设计模式—设计模式之享元模式(第四周)

119 阅读3分钟

背景:

书接上文,自从小犬把天堂咖啡厅的项目做完之后,瞬间在天庭的技术圈是名声四起,是公认的大牛级人物了, 昨天又顺利牵到玉兔的小手,弄得这只万年单身汪兴奋到了后半夜,今天小犬刚从美梦中醒来接到了一个电话,一看来显,哪吒三太子, 该不会是系统出问题了吧,赶紧接听,原来是天庭职称考试,哪吒居然报了个技术岗位,于是哪吒最近狂补技术知识,这不昨天看到了 享元模式,死活理解不了(毕竟三头六臂,不太理解共享),这不找到技术大牛哮天犬了。

小犬一听,享元模式,这个倒不是很难,于是就有了一下的介绍。

定义:

如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行, 这样即节省内存,又可以减少创建对象的过程,提高运行速度。共享一个对象。享元模式是池技术的重要实现方式,缓存。

UML图:(网上找的)

享元模式UML.png

Flyweight是抽象享元角色。它是产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现; 内在状态:不随环境的变化而变化,上面例子中不管位置如何变化,A就是A。字母A就是内在状态。 外在状态:会随着环境的变化而变化,上面例子中位置变化所以输出的位置也是不一致的。字母A的位置就是外在状态

ConcreteFlyweight是具体享元角色,是具体的产品类,实现抽象角色定义的业务;

UnsharedConcreteFlyweight是不可共享的享元角色,一般不会出现在享元工厂中;

FlyweightFactory是享元工厂,它用于构造一个池容器,同时提供从池中获得对象的方法。

案例图:

共享案例图.png

享元工厂角色:这个角色主要负责创建和管理享元角色。判断是否存在符合要求的享元对象,如果存在则直接拿取,如果不存在的话就会创建一个享元对象并保存。

抽象享元角色:这个角色是所有享元角色的基类。提供需要实现的公共接口

具体享元角色:继承于抽象享元角色。实现其抽象的接口。

客户端:负责调用并处理逻辑,且保存多有享元对象的状态

代码如下:

Flyweight抽象类

abstract class Flyweight(extrinsic:String) {
    //内部状态
    lateinit var intrinsic:String

    //外部状态,享元角色必须受外部状态
    protected val extrinsic = extrinsic

    /**
     * 定义业务操作
     */
    abstract fun operate(extrinsic:Int)

}

继承Flyweight超类或实现Flyweight接口,并为其内部状态增加存储空间

class ConcreteFlyweight(extrinsic:String):Flyweight(extrinsic) {

    override fun operate(extrinsic: Int) {
        Log.v("===========","具体Flyweight:$extrinsic")
    }

}

指那些不需要共享的Flyweight子类

class UnsharedConcreteFlyweight(extrinsic:String):Flyweight(extrinsic) {
    override fun operate(extrinsic: Int) {
        Log.v("=========","不共享的具体Flyweight:$extrinsic")
    }
}

一个享元工厂,用来创建并管理Flyweight对象,主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,

  • FlyweightFactory对象提供一个已创建的实例或创建一个实例。
object FlyweightFactory {

     var pool:HashMap<String,Flyweight> = hashMapOf()

    fun getFlyWeight(extrinsic:String):Flyweight?{
        var flyWeight:Flyweight ?= null

        if(pool.containsKey(extrinsic)){
            flyWeight = pool[extrinsic]
            Log.v("===========", "已有 $extrinsic 直接从池中取---->")
        }else{
            flyWeight = ConcreteFlyweight(extrinsic)
            pool[extrinsic] = flyWeight
            Log.v("===========", "创建 $extrinsic 并从池中取出---->")
        }

        return flyWeight
    }

}

点击实现:

var extrinsic = 22

findViewById<Button>(R.id.btnCreateX).setOnClickListener {
    val flyweightX: Flyweight = FlyweightFactory.getFlyWeight("X")!!
    flyweightX.operate(++extrinsic)
}
findViewById<Button>(R.id.btnCreateY).setOnClickListener {
    val flyweightY: Flyweight = FlyweightFactory.getFlyWeight("Y")!!
    flyweightY.operate(++extrinsic)

}
findViewById<Button>(R.id.btnCreateZ).setOnClickListener {
    val flyweightZ: Flyweight = FlyweightFactory.getFlyWeight("Z")!!
    flyweightZ.operate(++extrinsic)

}
findViewById<Button>(R.id.btnGetX).setOnClickListener {
    val flyweightReX: Flyweight = FlyweightFactory.getFlyWeight("X")!!
    flyweightReX.operate(++extrinsic)
}
findViewById<Button>(R.id.btnGetXX).setOnClickListener {
    val unsharedFlyweight: Flyweight = UnsharedConcreteFlyweight("X")
    unsharedFlyweight.operate(++extrinsic)
}

运行结果:

企业微信截图_16365051982344.png