[Swift设计模式] 静态工厂

413 阅读2分钟
更多内容,欢迎关注公众号:Swift花园
喜欢文章?不如来点赞关注吧

 

静态工厂的用例

命名构造器

静态工厂模式的头等好处是:每一个静态工厂方法都有一个自己的名字。Apple 在 UIColor 类实现中使用这个模式创建了许多命名颜色,比如 .red.yellow,等。 注意,Swift 中的这种实现并非是方法,而是静态属性,返回一个实际的实例。

public extension TimeInterval {
    public static var second: TimeInterval { return 1 }
    public static var minute: TimeInterval { return 60 }
    public static var hour: TimeInterval { return 3_600 }
    public static var day: TimeInterval { return 86_400 }
    public static var week: TimeInterval { return 604_800 }
}

记住一天或者一周有多少秒很困难吧?所以 TimeInterval.week604_80 好多了。 😅

 

缓存对象

静态工厂模式的第二个好处是:出于优化内存的考虑,你可以用它来实现缓存。利用静态构造器,你可以限制创建对象的数量。(即,静态工厂方法)。🏭

class Service {
    
    var name: String

    // MARK: - 缓存

    private static var cache: [String:Service] = [:]
    
    private static func cached(name: String) -> Service {
        if Service.cache[name] == nil {
            Service.cache[name] = Service(named: name)
        }
        return Service.cache[name]!
    }

    // MARK: - 静态工厂

    static var local: Service {
        return Service.cached(name: "local")
    }

    static var remote: Service {
        return Service.cached(name: "remote")
    }

    // MARK: - 初始化

    init(named name: String) {
        self.name = name
    }
}

 

私有化构造域

静态工厂的另一个好处是你可以利用它将一个类的构造过程限制在 private 访问级别。换句话说,创建过程只能通过静态工厂方法来完成。你只需要将 init 方法声明为 private。

public final class Service {

    var name: String

    private init(name: String) {
        self.name = name
    }

    public static var local: Service {
        return Service(name: "local")
    }

    public static var remote: Service {
        return Service(name: "remote")
    }
}

注意,你可以利用 final 和 static 关键字来限制继承。如果要开放继承,你需要移除 final 关键字,同时在属性中用 class 关键字替换 static,这样子类才能重写工厂方法。🤔

 

静态方式返回

让我们更进一步。你其实可以用静态方法返回任何类型,这种用法跟静态工厂很相似,应用场景十分广泛。😛

extension UIColor {
    
    private static func image(with color: UIColor) -> UIImage {
        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(color.cgColor)
        context.fill(rect)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img!
    }
    
    static var redImage: UIImage {
        return UIColor.image(with: .red)
    }
}

 

我的公众号

这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~