iOS 21种设计模式之工厂模式

原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
我的stackoverflow

profile for Leo on Stack Exchange, a network of free, community-driven Q&A sites


感谢

感谢《Pro Objective-C Design Pattern for iOS》一书,这个博客系列由很多灵感源自次书。同时,也感谢Wiki以及一些博客博主。每篇文章最后,都会列出参考链接。

设计模式是为了解决一类问题而出现的,要深刻理解某个模式的应用场景,优点,缺点。千万不要为了使用而实用,那样很可能写出不伦不类的东西。

对于同一种模式,每个人的理解都不同,能解决实际问题才是关键


什么是工厂模式?

工厂是用来生产产品的。在iOS开发中,产品就是类的对象,工厂就是工厂方法。
工厂模式就是定义创建对象的接口,让子类决定实例化哪一个类。这样,类的实例化就推迟到了子类

先看看工厂模式提供的接口,也就是客户端(API使用者)调用的接口

	 let factory:Factory = ...//获取工厂对象
	 let product:Product = factory.createProduct()//这里获得到的可能是Product,也可能是Product的子类

可以看到,客户端只需要关注Factory和Product两个类即可,而不需要关注他的子类到底是啥


解决什么问题?

类有一组子类,可以共用一套接口,但是实例化的方式略有差异。用工厂的方式实现,使得客户端(类的调用着)能够专注于接口。而不需要访问具体的实现类。


什么时候使用工厂模式?

  • 编译器无法定义创建对象类
  • 类可以让其子类决定在运行期具体实例化的对象

实现原理

  • 接口定义:工厂类的接口定义可以是类,也可以是协议。
  • 工厂方法定义:

工厂模式的UML图

  • 注意其中红线圈住的部分,那是实际的客户端(API调用着)接触的部分,也就是你设计的接口。在面向对象编程里有个关键的概念:面向接口编程,而不是面向实现编程

对于,客户端来说,只需要接触工厂基类或者协议,得到产品基类就行了。

  • 比如,有一个鞋厂,它告诉我,跟他的代表人(工厂方法)说生产鞋子就行了,今天来的是跑鞋厂的代表,我跟他说生产鞋子,他就给我一双跑鞋。这样,我只需要专注一点:跟我要接触的代表人(工厂方法)说生产鞋子(统一接口),我就能够拿到对应的产品(实例)而我只关心鞋子的通用属性,不关心具体属性
iOS 21种设计模式之工厂模式_第1张图片

一个简单例子

Swift的例子采用协议作为抽象基础类,用一个方法来返回不同的对象。

//产品
protocol Shoes{
    func logDescription();
}
class RunningShoes:Shoes{
    func logDescription() {
        NSLog("跑鞋")
    }
}
class Sneakers:Shoes{
    func logDescription() {
        NSLog("板鞋")
    }
}
//工厂
protocol Factory{
    func createShoes()->Shoes;
}
class RunningShoesFactory:Factory{
    func createShoes() -> Shoes {
        return RunningShoes()
    }
}
class SneakerFactory:Factory{
    func createShoes() -> Shoes {
        return Sneakers()
    }
}
//模拟Runtime的不确定性
class SimulateDynamicFactory{
   class func simulateFactory()->Factory{
        let randomInt = random()%2
        if randomInt == 0{
            return RunningShoesFactory()
        }else{
            return SneakerFactory()
        }
    }
}

然后,看看客户端代码

let factory:Factory = SimulateDynamicFactory.simulateFactory()
let product = factory.createShoes()
product.logDescription()

可能有同学问了,我为何不直接访问shoes的对象,直接调用构造方法(),岂不是更简单直接。面向对象开发还有一个原则对扩展开发,对修改封闭。如果直接使用if else 进行Shoes(),那么当有一种新的鞋子出现的时候,客户端将不得不修改大量代码来支持新的鞋子。而使用工厂模式,由于接口始终是一直的,客户端几乎不需要修改什么代码。只需要扩展一类产品,增加一个Factory就可以了。

举个例子,假如我对上文的例子进行扩展,增加一类新的鞋子叫做leoShoes,我需要增加的代码是这样的


class LeoShoes:Shoes{
    func logDescription() {
        NSLog("扩展鞋子")
    }
}
class LeoShoesFactory:Factory{
    func createShoes() -> Shoes {
        return LeoShoes()
    }
}

然后,修改SimulateDynamicFactory.simulateFactory方法,看到了吧,客户端代码不用任何修改,假如你是在一个Team负责给别的人开发库,那么库的使用者肯定会谢谢你,否则你每发布一个版本,他都要修改调用


参考链接

  • WIKI Factory Design Pattern

下一篇

  • 抽象工厂模式

你可能感兴趣的:(设计模式)