11.FlyweightPattern - QDDCoder/LZLearniOS GitHub Wiki

享元模式

解释地址:https://www.runoob.com/design-pattern/flyweight-pattern.html

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式

 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象
 
 
 
 
 意图:运用共享技术有效地支持大量细粒度的对象
 
 主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建
 
 何时使用: 1系统中有大量对象 2这些对象消耗大量内存 3这些对象的状态大部分可以外部化 4这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替 5系统不依赖于这些对象身份,这些对象是不可分辨的
 
 如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象
 
 关键代码:用 HashMap 存储这些对象
 
 应用实例: 1JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面 2数据库的数据池
 
 优点:大大减少对象的创建,降低系统的内存,使效率提高
 
 缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱
 
 使用场景: 1系统有大量相似对象 2需要缓冲池的场景
 
 注意事项: 1注意划分外部状态和内部状态,否则可能会引起线程安全问题 2这些类必须有一个工厂对象加以控制

1.创建一个接口。

protocol ShapeFlyweight {
    func draw()
}

2.创建实现接口的实体类。

class CircleFlyweight: NSObject,ShapeFlyweight {
    
    private var color:String?
    private var x:Int?
    private var y:Int?
    private var radius:Int?
    
    init(with color:String) {
        super.init()
        self.color = color
    }
    
    func setX(with x:Int)  {
        self.x = x
    }
    
    func setY(with y:Int)  {
        self.y = y
    }
    
    func setRadius(with radius:Int)  {
        self.radius = radius
    }
    
    func draw() {
        print("Circle: Draw() [Color :\(color ?? ""),x:\(x ?? 0),y:\(y ?? 0),radius:\(radius ?? 0)")
    }
}

3.创建一个工厂,生成基于给定信息的实体类的对象

class ShapeFlyweightFactory: NSObject {
    private static var circleMap:[String:ShapeFlyweight] = [String:ShapeFlyweight]()
    
    static func getCircle(with color:String) -> ShapeFlyweight {
        var circle = circleMap[color]
        if circle == nil {
            circle = CircleFlyweight(with: color)
            circleMap[color] = circle
            print("Creating circle of color : \(color)")
        }
        return circle!
    }
}
  • 测试

let colors:[String] = ["Red", "Green", "Blue", "White", "Black"]
override func viewDidLoad() {
    super.viewDidLoad()
    for i in 0 ..< 20 {
        let circle = ShapeFlyweightFactory.getCircle(with: getRandomColor())
        if let cc:CircleFlyweight = circle as? CircleFlyweight {
            cc.setX(with: getRandomX())
            cc.setY(with: getRandomY())
            cc.setRadius(with: 100)
            cc.draw()
        }
    }
}

func getRandomColor() -> String {
    return colors[Int.randomIntNumber(lower: 0, upper: colors.count)]
}

func getRandomX() -> Int {
    return Int.randomIntNumber(lower: 0, upper: 100)
}

func getRandomY() -> Int {
    return Int.randomIntNumber(lower: 0, upper: 100)
}
  • 测试结果

Creating circle of color : Red
Circle: Draw() [Color :Red,x:7,y:79,radius:100
Creating circle of color : White
Circle: Draw() [Color :White,x:71,y:97,radius:100
Creating circle of color : Blue
Circle: Draw() [Color :Blue,x:21,y:9,radius:100
Creating circle of color : Black
Circle: Draw() [Color :Black,x:43,y:37,radius:100
Circle: Draw() [Color :Red,x:50,y:26,radius:100
Circle: Draw() [Color :Red,x:97,y:39,radius:100
Circle: Draw() [Color :Black,x:53,y:20,radius:100
Circle: Draw() [Color :Red,x:76,y:8,radius:100
Creating circle of color : Green
Circle: Draw() [Color :Green,x:15,y:72,radius:100
Circle: Draw() [Color :Blue,x:75,y:77,radius:100
Circle: Draw() [Color :White,x:87,y:26,radius:100
Circle: Draw() [Color :Black,x:63,y:60,radius:100
Circle: Draw() [Color :Green,x:37,y:1,radius:100
Circle: Draw() [Color :Blue,x:24,y:94,radius:100
Circle: Draw() [Color :Red,x:15,y:63,radius:100
Circle: Draw() [Color :Black,x:40,y:81,radius:100
Circle: Draw() [Color :Green,x:58,y:53,radius:100
Circle: Draw() [Color :White,x:4,y:93,radius:100
Circle: Draw() [Color :Black,x:9,y:59,radius:100
Circle: Draw() [Color :Red,x:37,y:2,radius:100
⚠️ **GitHub.com Fallback** ⚠️