设计模式-22.享元模式

511 阅读1分钟

一句话总结

运用共享技术有效地支持大量细粒度对象。

需求

现在要给几个客户分别开发网站,有个要求展示产品,有的是博客。该怎么设计呢?是不要给每个客户都要申请一个云服务器?

享元模式示例

static func main() {
    var extrinsicState = 22

    let f = FlyweightFactory()

    extrinsicState -= 1
    let fx = f.getFlyweight(key: "X")
    fx?.operation(extrinsicState: extrinsicState)

    extrinsicState -= 1
    let fy = f.getFlyweight(key: "Y")
    fy?.operation(extrinsicState: extrinsicState)

    extrinsicState -= 1
    let fz = f.getFlyweight(key: "Z")
    fz?.operation(extrinsicState: extrinsicState)

    extrinsicState -= 1
    let uf = UnsharedConcreteFlyweight()
    uf.operation(extrinsicState: extrinsicState)
}

protocol Flyweight {
    func operation(extrinsicState: Int)
}

class ConcreteFlyweight: Flyweight {
    func operation(extrinsicState: Int) {
        print("具体Flyweight:\(extrinsicState)")
    }
}

class UnsharedConcreteFlyweight: Flyweight {
    func operation(extrinsicState: Int) {
        print("不共享的具体Flyweight:\(extrinsicState)")
    }
}

class FlyweightFactory {
    var dic: [String: Flyweight] = [:]

    init() {
        dic["X"] = ConcreteFlyweight()
        dic["Y"] = ConcreteFlyweight()
        dic["Z"] = ConcreteFlyweight()
    }

    func getFlyweight(key: String) -> Flyweight? {
        dic[key]
    }
}

Code V1.0

用享元模式实现网站需求,这样就可以两个网站实例下,满足4个人的需求。

static func main() {
    let f = WebSiteFactory()

    let fx = f.getWebSiteCategary(key: "产品展示")
    fx.use(user: User(name: "小X"))

    let fy = f.getWebSiteCategary(key: "产品展示")
    fy.use(user: User(name: "小Y"))

    let fz = f.getWebSiteCategary(key: "产品展示")
    fz.use(user: User(name: "小Z"))

    let fl = f.getWebSiteCategary(key: "博客")
    fl.use(user: User(name: "小L"))

    print("网站分类总数为: \(f.getWebSiteCount())")
}

protocol WebSite {
    func use(user: User)
}

class User {
    let name: String
    init(name: String) {
        self.name = name
    }
}

class ConcreteWebSite: WebSite {
    let name: String
    init(name: String) {
        self.name = name
    }

    func use(user: User) {
        print("网站分类:\(name),用户: \(user.name)")
    }
}

class WebSiteFactory {
    var flyweights: [String: WebSite] = [:]

    func getWebSiteCategary(key: String) -> WebSite {
        if flyweights[key] == nil {
            flyweights[key] = ConcreteWebSite(name: key)
        }
        return flyweights[key] ?? ConcreteWebSite(name: key)
    }

    func getWebSiteCount() -> Int {
        flyweights.values.count
    }
}

优点

可以避免大量相思类实例的开销,将共有不轻易改变部分称为内部状态,将差异化比如不同的账户称为外部状态。