iOS 21种设计模式之抽象工厂(Abstract Factory)

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

感谢

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

这个系列的文章

  • 工厂
  • 抽象工厂
  • 单例
  • 原型
  • 生成器
  • 适配器
  • 桥接
  • 中介者
  • 观察者
  • 组合
  • 迭代器
  • 访问者
  • 装饰
  • 责任链
  • 模版
  • 策略
  • 命令
  • 享元
  • 代理
  • 备忘录
  • 总结篇:MVC
  • 进阶篇:MVVM

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

对于同一种模式,每个人的理解都不同,能解决实际问题才是关键,所以,一定要搞清楚每种设计模式究竟解决了那一类问题,对于设计模式,可以首先理解设计出的接口,再理接口内部的实现

什么是抽象工厂?

抽象工厂是提供一个创建一系列的相互依赖的接口,而无需指定他们具体的类。

一般抽象工厂都是生成一组相互依赖的产品的,往往是多个。

当你用抽象工厂来进行设计的时候,客户端调用的接口应该是这样的

//客户端代码
let factory:AbstractFactory = //在Runtime决定
let product1:AbstractProduct1 = factory.createProduct1()
let product2:AbstractProduct2 = factory.createProduct2()

可以看到,客户端只需要访问工厂类,以及每个产品的抽象基类

解决什么问题?

-讲一组相关的类封装到一个抽象的接口来产生。客户端几乎完全解耦合,客户端只需要关注具体的抽象工厂以及抽象的产品,而不需要访问具体的类。

什么时候使用抽象工厂?

  • 编译器无法定义创建对象类
  • 类可以让其子类决定在运行期具体实例化的对象
  • 封装一组相互关联的类的创建

实现原理

  • 接口定义:工厂类和抽象产品产品的的接口定义可以是类,也可以是协议
  • 工厂方法定:工厂方法返回抽象基础类对象
  • 具体类要至少重载所有抽象类定义的接口

抽象工厂模式的UML图

其中红色部分是客户端实际需接触的部分

iOS 21种设计模式之抽象工厂(Abstract Factory)_第1张图片

Swift的一个简单例子

Swift的例子采用协议作为抽象基础类

//产品相关

//产品一,phone
protocol Phone{
    func call();//所有的手机都能打电话
}
class Samsung:Phone{
    func call(){
        print("Call from Samsung");
    }
}
class IPhone:Phone{
    func call(){
        print("Call from iPhone")
    }
}

//产品二,Usb
protocol USB{
    func use();
}
class SamsungUSB:USB{
    func use(){
        print("USB for Samsung");
    }
}
class IphoneUSB:USB{
    func use(){
        print("USB for IPhone");
    }
}

//工厂相关

protocol PhoneRelatedFactory{
    func createPhone()->Phone;
    func createUSB()->USB;
}
//实际工厂一,负责生产三星的相关产品
class SamsungFactory:PhoneRelatedFactory{ func createPhone() -> Phone { return Samsung() } func createUSB() -> USB { return SamsungUSB() } } class IphoneFactory:PhoneRelatedFactory{ func createPhone() -> Phone { return IPhone() } func createUSB() -> USB { return IphoneUSB() } } 

//模拟不确定使用的产品

class SimulateDynamicFactory{
    class func simulateFactory()->PhoneRelatedFactory{
        let randomInt = random()%2
        if randomInt == 0{
            return SamsungFactory()
        }else{
            return IphoneFactory()
        }
    }
}

//客户端代码

let factory = SimulateDynamicFactory.simulateFactory()

let phone = factory.createPhone()
let usb = factory.createUSB()

phone.call()
usb.use()

假如,抽象工厂有一种新的产品到来的时候,
要修改抽象工厂类的接口func createNetProduct()->NewProduct;,然后仿照上述的方式增加对应的产品,和实际工厂类.

对于客户端来说,原有代码不需要任何修改,只需要在需要新产品的地方增加相关代码即可。对扩展开放,对修改封闭

工厂模式 VS 抽象工厂模式

工厂模式 抽象工厂模式
创建一种产品 创建一组相互依赖产品
通过对象继承创建抽象产品 通过对象组合创建抽象产品
必须修改父类接口支持心的产品 子类化创建着,并且重载新的方法来支持新的产品

类簇

类簇和工厂模式很类似,它通过在基类中提供工厂方法,隐藏具体的子类实现。例如Cocoa中的类方法

    NSNumber * a = [NSNumber numberWithBool:YES];
    NSNumber * b = [NSNumber numberWithInteger:123];
    NSLog(@"%@",NSStringFromClass([a class])); //__NSCFBoolean
    NSLog(@"%@",NSStringFromClass([b class])); //__NSCFNumber

可以看到实际上NSNumber的Runtime类并不是NSNumber,NSNumber只是定义了一个高度抽象的基类,它既是产品类,又是工厂类。通过提供numberWith***一些列方法,隐藏了具体的子类实现。类似的还有[UIButton buttonWithType:].Cocoa中,使用类簇的设计模式有NSDictionary,NSData,NSString等。
一个类簇的例子


class Shoes{
    class func runningShoes()->Shoes{
        return RunningShoes(name:"跑鞋")
    }
    class func sneaker()->Shoes{
        return Sneaker(name:"板鞋")
    }
    let name:String
    init(name:String){
        self.name = name
    }
}
private class RunningShoes:Shoes{
   //Other custom impeletion
}
private class Sneaker:Shoes{

}

参考链接

  • WIKI Abstract Factory Design Pattern

你可能感兴趣的:(设计模式,ios,抽象工厂)