美文网首页iOS学习笔记iOS开发技术分享iOS学习开发
iOS&设计模式 - 构建者模式(Builder)

iOS&设计模式 - 构建者模式(Builder)

作者: YxxxHao | 来源:发表于2017-06-25 16:53 被阅读490次

什么是构建都模式

将一个复杂对象的创建和表示进行分离,根据创建顺序不一样,表示的方式也不一样。如买手机时选择配置:iPhote7、玫瑰金、64g,你可以选择不同配置,但你却不知道他是如果实现的,同时也因为的选择配置的不同,生产的工艺和手机样式也不一样。用户不需要知道如何实现的,只选择最终的表示,这就是现实生活中构建者模式。

标准组成

  • 抽象构建器(Builder):为构建器提供接口(iOS 中的协议)
  • 具体构建器(ConcreteBuilder):构建具体的产品(实现 Builder 协议)
  • 指挥者(Director):调用Builder接口來创建产品对象(这个不一定需要,可有可无)
  • 产品角色(Product):具体的产品

结构

图片.png

图上的指挥者(组装器)是不一定需要的,因为我们可以直接 iPhoneBuilder 来组装产品,而不需要再单独封闭一个类来实现,但要与不要,还是需要根据业务场景来确定,设计模式是死的,人是活的,至于怎么使用,还是那句话:按实际需求。

实现

这里实现一个日期的构建者:

// let bulider = DateBulider()
// bulider.setYear(2017).setMonth(5).setDay(25).setHour(11).setMinute(41).showDate()

class DateBulider: NSObject {  
    private var component: NSDateComponents?
    override init() {
        component = NSDateComponents()
        // default
        component?.calendar = Calendar(identifier: .gregorian)
    }
    func date() -> Date {
        return (component?.date)!
    }
    func showDate() {
        let formatter = DateFormatter()
        formatter.dateFormat = "yy-MM-dd hh:mm:ss"
        print(formatter.string(from: (component?.date)!))
    }
    func setCalender(identifier: Calendar.Identifier)  -> DateBulider {
        component?.calendar = Calendar(identifier: identifier)
        return self
    }
    func setSecond(_ second: Int) -> DateBulider {
        component?.second = second
        return self
    }
    func setMinute(_ minute: Int) -> DateBulider {
        component?.minute = minute
        return self
    }
    func setHour(_ hour: Int) -> DateBulider {
        component?.hour = hour
        return self
    }
    func setDay(_ day: Int) -> DateBulider {
        component?.day = day
        return self
    }
    func setMonth(_ month: Int) -> DateBulider {
        component?.month = month
        return self
    }
    func setYear(_ year: Int) -> DateBulider {
        component?.year = year
        return self
    }
}

上例的构建者,非严格标准的构建者,下面按标准来做,实现抽象构建器(DateBuilder Protocole):

protocol DateBuliderProtocole: class {
    func date() -> Date
    func showDate()
    func setCalender(identifier: Calendar.Identifier)  -> DateBulider
    func setSecond(_ second: Int) -> DateBulider
    func setMinute(_ minute: Int) -> DateBulider
    func setHour(_ hour: Int) -> DateBulider
    func setDay(_ day: Int) -> DateBulider
    func setMonth(_ month: Int) -> DateBulider
    func setYear(_ year: Int) -> DateBulider
}

并在 DateBulider 实现该 Protocole:

class DateBulider: DateBuliderProtocole {...}

到这里,这个例子可以说是比较标准的简单的构建者模式,Director 和 Product 并没有出现,但 Director 是不一定需要的,Product 部分也可以说是:

let bulider = DateBulider()
bulider.setYear(2017).setMonth(5).setDay(25).setHour(11).setMinute(41).showDate()

但这里没有封装成一个 Product 类,如果在复杂的场景下,Product 类还是需要有的。

非标准构建者模式

设计模式是一种思想,不是一成不变的,就构建者模式来说,实际中使用构建者模式很多者是标准模式的中变形,不过思想都是一样的,万变不离其宗。

下面了解下 Realm 中使用到的构建者模式,关于 Realm 的介绍就不多说了,一句话:

第一个专门针对移动平台设计的数据库,目标是取代SQLite。

Realm 中的数据库操作就是使用构建者模式,如:

// 添加/更新
realm.add(model, update: true)

// 删除
realm.delete(model)

// 查询条件
realm.objects(YHFeedItemModel.self).filter("isDel = false").filter("isFavorite = true")

这里就是构建者模式的一种应用,将一个复杂对象的创建和表示进行分离。如添加功能中,我们输入正确的实例就可以完成保存,但底层他到底是怎么实现的我们并不知道,而且我们也不关心。我们可以下载 Realm 的源码来看下的实现(大概知道流程就可以了,有兴趣的可以单独去下完整的源码看):

// Swift 
public func add(_ object: Object, update: Bool = false) {
    if update && object.objectSchema.primaryKeyProperty == nil {
        throwRealmException("'\(object.objectSchema.className)' does not have a primary key and can not be updated")
    }
    RLMAddObjectToRealm(object, rlmRealm, update)
}

// OC
void RLMAddObjectToRealm(__unsafe_unretained RLMObjectBase *const object,
                         __unsafe_unretained RLMRealm *const realm,
                         bool createOrUpdate) {
    RLMVerifyInWriteTransaction(realm);

    // verify that object is unmanaged
    if (object.invalidated) {
        @throw RLMException(@"Adding a deleted or invalidated object to a Realm is not permitted");
    }
    if (object->_realm) {
        if (object->_realm == realm) {
            // Adding an object to the Realm it's already manged by is a no-op
            return;
        }
        // for differing realms users must explicitly create the object in the second realm
        @throw RLMException(@"Object is already managed by another Realm. Use create instead to copy it into this Realm.");
    }
    if (object->_observationInfo && object->_observationInfo->hasObservers()) {
        @throw RLMException(@"Cannot add an object with observers to a Realm");
    }

    auto& info = realm->_info[object->_objectSchema.className];
    RLMAccessorContext c{realm, info, true};
    object->_info = &info;
    object->_realm = realm;
    object->_objectSchema = info.rlmObjectSchema;
    try {
        realm::Object::create(c, realm->_realm, *info.objectSchema, (id)object,
                              createOrUpdate, &object->_row);
    }
    catch (std::exception const& e) {
        @throw RLMException(e);
    }
    object_setClass(object, info.rlmObjectSchema.accessorClass);
    RLMInitializeSwiftAccessorGenerics(object);
}

这里就不详细读 Realm 的源码了,大概了解它的实现就可以了,主要是理解构建者模式的思想,关于构建者模式的内容就说到这里了,有空闲时候话,再简单写一个复杂一点 Demo 来补充说明了。

Demo可以从这里下载

-------------一般般的分割线 17.07.23 更新-------------

通过构建者实现自定义 UIAlertView

在最近开发中,需要实现一个支持添加图片的 AlertView,顺便也实践下构建者模块,直接上代码:

class JCAlertView: NSObject {  
    private var alertView: UIAlertView!
    private override init() {}
    static func bulid() -> JCAlertView {
        let alertView = UIAlertView()
        let alert = JCAlertView()
        alert.alertView = alertView
        return alert
    }
    public func setDelegate(_ delegate: AnyObject?) -> JCAlertView {
        alertView.delegate = delegate
        return self
    }
    public func setTitle(_ title: String) -> JCAlertView {
        alertView.title = title
        return self
    }
    public func setMessage(_ message: String) -> JCAlertView {
        alertView.message = message
        return self
    }
    public func setTag(_ tag: Int) -> JCAlertView {
        alertView.tag = tag
        return self
    }
    public func addButton(_ buttonTitle: String) -> JCAlertView {
        alertView.addButton(withTitle: buttonTitle)
        return self
    }
    public func addCancelButton(_ buttonTitle: String) -> JCAlertView {
        alertView.addButton(withTitle: buttonTitle)
        let count = alertView.numberOfButtons
        alertView.cancelButtonIndex = count - 1
        return self
    }
    public func  addImage(_ image: UIImage) -> JCAlertView {
        let imageView = UIImageView()
        let scale = 270 / image.size.width
        imageView.image = image.resizeImage(image: image, newSize: CGSize(width: image.size.width * scale, height: image.size.height * scale))
        alertView.setValue(imageView, forKey: "accessoryView")
        return self
    }
    public func show() {
        alertView.show()
    }
}

相关文章

  • iOS&设计模式 - 构建者模式(Builder)

    什么是构建都模式 将一个复杂对象的创建和表示进行分离,根据创建顺序不一样,表示的方式也不一样。如买手机时选择配置:...

  • Mybatis中的设计模式

    Mybatis 设计模式 mybaits最少用到了九种设计模式: 设计模式mybaits体现Builder构建者模...

  • 安卓设计模式-构建者模式

    安卓设计模式-构建者模式 是什么 构建者模式又生builder模式,是将复杂的对象的构建与他的表示分离,使得同样的...

  • 设计模式--Builder

    标签(空格分隔): android 设计模式 builder 1 Builder设计模式概述 将复杂对象的构建与它...

  • Builder模式

    一、作用 工匠若水-设计模式(创建型)之建造者模式(Builder Pattern) 用于构建复杂的对象,将构建的...

  • Android Builder模式笔记

    Builder模式介绍 Builder模式又称建造者模式,表示将构建过程和表示过程进行分离,让(参数)构建过程变得...

  • 【设计模式】- Builder(构建者)模式

    简介 当我们在构建一个复杂的对象时,想要把对象的构建和表现分离开来,那么就可以使用Builder模式。比如:构建一...

  • 设计模式-Builder模式(构建者模式)

    为什么要用Builder模式?什么时候用? Builder模式一般用于构造一个复杂对象时使用,可以屏蔽构造的细节,...

  • 建造者模式(Builder 模式)

    Android进阶之设计模式 建造者模式( Builder 模式) 定义:将一个复杂对象的构建与它的表示分离,使得...

  • 2.创建者模式——Builder

    设计模式——创造者模式(Builder)

网友评论

    本文标题:iOS&设计模式 - 构建者模式(Builder)

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