美文网首页
【设计模式】17 - 享元模式 (Flyweight Patte

【设计模式】17 - 享元模式 (Flyweight Patte

作者: Lebron_James | 来源:发表于2019-05-06 19:28 被阅读0次

    这篇文章是我阅读raywenderlich.comDesign Patterns by Tutorials的总结,文中的代码是我阅读书本之后根据自己的想法修改的。如果想看原版书籍,请点击链接购买。


    享元模式属于创建型模式,通过复用内存中的对象,减少内存的占用。

    这个模式涉及两个部分:1)flyweight对象;2)创建 flyweight 的方法。

       +---------------------------------------------+ 
       |                Flyweight                    |
       +---------------------------------------------+ 
       |  static flyweight: SomeObjectType           |
       +---------------------------------------------+ 
       |  static flyweight(for:) -> SomeObjectType   |
       +---------------------------------------------+ 
    

    其实,享元模式很像单例模式,他们都有让整个程序共享某个对象的特性。但是,在享元模式中,可以拥有多个同一类型的对象。例如,我们UIColor中的各种系统自带的颜色,每一种颜色都是一个单例。

    什么时候使用

    在需要使用多个不同配置的单例时使用。

    简单demo

    iOS 中用到的享元模式

    上面提到了UIColor其实是使用了享元模式,我们来验证一下:

    let black1 = UIColor.black
    let black2 = UIColor.black
    print(black1 === black2)  // true
    

    结果是 true,很明显black是一个单例。

    来看看我们自己创建的黑色:

    let black3 = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
    let black4 = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
    print(black3 === black4)  // false
    

    都是黑色,但是他们是不同的对象。

    我们再看看UIFont

    let font1 = UIFont.systemFont(ofSize: 15)
    let font2 = UIFont.systemFont(ofSize: 15)
    print(font1 === font2)  // true
    

    结果也是 true,说明UIFont也是使用了享元模式。

    Demo

    在开发中,难免会遇到自定义字体的需求,这里以自定义字体为例,假设在项目中要用到SFUIText这个系列的字体:

    extension UIFont {
        
        enum SFUITextFontStyle: String {
            case medium = "SFUIText-Medium"
            case regular = "SFUIText-Regular"
            case heavy = "SFUIText-Heavy"
            case bold = "SFUIText-Bold"
            case semibold = "SFUIText-Semibold"
        }
        
        static var SFUITextFonts: [String: UIFont] = [:]
        
        static func SFUITextFont(style: SFUITextFontStyle,
                                 size: CGFloat) -> UIFont? {
            
            let key = "\(style.rawValue)\(size)"
            if let font = SFUITextFonts[key] {
                return font
            }
            
            let font = UIFont(name: style.rawValue, size: size)
            SFUITextFonts[key] = font
            return font
        }
    }
    

    首先用枚举列举了字体的粗细程度;然后定义SFUITextFonts来存储创建过的字体;最后定义一个创建字体的方法,如果已经创建过的字体,则直接在缓存中取出。

    我们来验证一下:

    let font1 = UIFont.SFUITextFont(style: .heavy, size: 20)
    let font2 = UIFont.SFUITextFont(style: .heavy, size: 20)
    print(font1 == font2)  // true
    

    结果是 true

    总结

    在使用享元模式的过程中,需要考虑缓存数据是否很增长得很大。虽然我们用缓存来保存了一些对象,避免重复创建,以减少内存的使用,但是也有可能缓存会占用比较大的内存。所以我们可能要考虑设定缓存的最大占用内存,如果超过了设定值,则把以前的数据删掉,保留最近的数据。

    另外还要注意的是,享元模式只能用于 Class 类型,不能用于 Struct 类型,因为 Struct 类型是值类型,

    欢迎加入我管理的Swift开发群:536353151

    下一篇文章:【设计模式】18 - 中介者模式 (Mediator Pattern)

    相关文章

      网友评论

          本文标题:【设计模式】17 - 享元模式 (Flyweight Patte

          本文链接:https://www.haomeiwen.com/subject/wuadoqtx.html