陈江川

邮箱:jiangchuanc@gmail.com

工厂方法模式和抽象工厂方法模式的区别

工厂方法模式 抽象工厂方法模式
通过类继承创建抽象产品 通过组合对象创建抽象产品
生产单一的产品 生产多个系列的产品
通过子类化Creator,并且重载父类的工厂方法创建产品 子类化Creator,不重载父类的工厂方法,但是通过修改父类的多个接口,达到创建多个产品

应用场景

工厂方法模式

  1. 我想要一部手机(这个手机是抽象,因为没有具体说要什么品牌的手机):Phone
  2. 需要一个工厂生产手机(这个工厂也是抽象,因为并没具体让哪家工厂生产手机):PhoneCreator
  3. 工厂要有生产线(生产产品的接口):- (Phone *)createPhone;
Phone.h

@interface Phone : UIView

@end
Phone.m

@implementation Phone

@end
PhoneCreator.h

@interface PhoneCreator : NSObject
- (Phone *)createPhone;
@end
PhoneCreator.m

@implementation PhoneCreator

- (Phone *)createPhone {
    return [[Phone alloc] init];
}

@end

现在,我想让富士康帮我生产iPhone:
1. iPone属于手机的一类,继承Phone;
2. 富士康属于工厂,继承PhoneCreator;

iPhone.h

@interface iPhone : Phone

@end
iPhone.m

@implementation iPhone

- (instance)init {
    self = [super init];
    if (self) {
        NSLog(@"可以在iPhone内部添加一个特有的东西");
    }
    return self;
}

@end
Foxconn.h

@interface Foxconn : PhoneCreator
@end

Foxconn.m

@implementation Foxconn

// 通过重载父类的工厂方法创建单一产品 
- (iPhone *)createPhone {
    // iPhone是通过继承Phone来创建产品的
    return [[iPhone alloc] init];
}
@end

最后我通过以下步骤就能得到iPhone了:

Foxconn *foxconn = [[Foxconn alloc] init];
Phone *phone = [foxconn createPhone];

抽象工厂模式

现在生产了一部手机,但是要贴两个不同公司(Apple,Mi)的牌子,所以在每个有公司logo的的地方我们都得改。假设手机的背部logo:backLogoView,home键:homeButton。

  1. 我们要有一个工厂Factory;
  2. Factory有一个生产线(工厂方法):+ (instance)factory; 这个方法决定了把该生产线变成生产Apple手机的生产线还是Mi手机的生产线;
  3. Factory中还有其它的接口返回对应品牌的东西,比如backLogoView、homeButton。
Factory.h

@interface Factory : NSObject
+ (instance)factory;
- (UIView *)backLogoView;
- (UIbutton *)homeButton;
@end

Factory.m

@implemetation Factory 

+ (instance)factory {
#if APPLE
    return [[AppleFactory alloc] init];
#else if MI
    return [[MIFactory alloc] init];
#else
    return nil;
#end
}

- (UIView *)backLogoView {
    return nil;
}

- (UIButton *)homeButton {
    return nil;
}

@end
生产苹果手机
AppleFactory.h

@interface AppleFactory : Factory 
@end

AppleFactory.m

@implemetation AppleFactory 

// 没有重载父类的工厂方法来创建产品;
// 而是通过修改父类的接口创建多个产品。
// 并没有通过类继承的方式创建产品,而是通过组合对象的方式

- (AppleBackLogoView *)backLogoView {
    return [[AppleBackLogoView alloc] init];
}

- (AppleHomeButton *)homeButton {
    return [[AppleHomeButton alloc] init];
}

@end
生产小米手机
MiFactory.h

@interface MiFactory : Factory 
@end

MiFactory.m

@implemetation MiFactory 

// 没有重载父类的工厂方法来创建产品;
// 而是通过修改父类的接口创建多个产品。

- (MiBackLogoView *)backLogoView {
    return [[MiBackLogoView alloc] init];
}

- (MiHomeButton *)homeButton {
    return [[MiHomeButton alloc] init];
}

@end

最后根据当前的手机品牌生产对应的手机:

// 创建工厂
Factory *factory = [Factory factory];
// 如果现在生产的是Apple,那么返回的backLogoView类型是:AppleBackLogoView
UIView *backLogoView = [factory backLogoView];

工厂方法模式Demo

主题切换
如果只是简单的改变所有ViewController中View的背景图片,使用工厂方法模式;
但如果涉及到更多View的定制,使用抽象工厂模式更好。

« Xcode8如何使用插件 podspec »