美文网首页
iOS 设计模式的应用 ② 工厂方法

iOS 设计模式的应用 ② 工厂方法

作者: _涼城 | 来源:发表于2022-05-05 07:50 被阅读0次

前言

    几乎在每个面向对象语言写的应用程序里都能看到工厂方法。对象工厂与生成有形产品的真实工厂类似,例如:制鞋厂生产鞋,手机工厂生产手机。比方说,你让工厂给你生产些产品,发送一个 “生产产品” 的消息,工厂按照相同的 “生产产品的协议” ,启动其生产线,过程结束后,每个厂家都返回所生产的特定类型的产品。我们把 ”生产“ 这个有魔力的词称作工厂方法,因为它是命令生产者得到想要的产品的方法。

什么是工厂方法模式

    工厂方法,也成为虚构造器。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂方法模式使其创建过程延迟到子类进行。其从代码中消除了对特有类的耦合,只需处理抽象接口,同一代码得到复用。

工厂方法模式的类图.png

    抽象的 Product 定义了工厂方法创建的对象的接口,ConcreteProduct 实现了 Product 的接口。Factory 定义了返回 Product 对象的工厂方法,ConcreteFactory 重载了工厂方法,返回 ConcreteProduct 实例。

什么时候使用工厂方法

  • 编译时无法准确预期要创建的对象的类
  • 类想让其子类决定在运行时创建什么
  • 类有若干辅助类为其子类,将返回哪个子类这一信息局部化。

工厂方法使用场景举例

  1. 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
  2. 数据库访问:当不知道最后系统采用哪一类数据库,以及数据库可能有变化时。

工厂方法的优缺点

优点:

  1. 一个调用者想创建一个对象,只要知道其名称就可以了。
  2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以,无需调用的代码
  3. 屏蔽产品的具体实现,调用者只关心产品的接口。

缺点

  1. 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

实现

普通工厂方法的实现

  1. 定义一个抽象 Shape 协议。

    @protocol Shape <NSObject>
    
    @property (nonatomic, copy) NSString *Id;
    
    @property (nonatomic, copy) NSString *type;
    
    - (void)draw;
    @end
    
  2. 定义三个 Shape 的子类分别为 RectangleCircleSquare

    @interface Rectangle : NSObject<Shape>
    @end
    @implementation Rectangle
    
    @synthesize Id;
    
    @synthesize type;
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.type =  @"Rectangle";
        }
        return self;
    }
    - (void)draw{
        NSLog(@"call Rectangle draw() method.");
    }
    
    @end
    
      
    @interface Circle : NSObject<Shape>
    @end
    @implementation Circle
    @synthesize Id;
    
    @synthesize type;
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.type =  @"Circle";
        }
        return self;
    }
    - (void)draw{
        NSLog(@"call Circle draw() method.");
    }
    @end
      
    @interface Square : NSObject<Shape>
    @end
    @implementation Square
    @synthesize Id;
    
    @synthesize type;
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.type =  @"Square";
        }
        return self;
    }
    - (void)draw{
        NSLog(@"call Square draw() method.");
    }
    @end
    
  1. 定义一个 ShapeFactory 抽象 @protocol,负责创建 Shape,以及遵守协调的 CircleFactoryRectangleFactorySquareFactory 负责创建 CircleRectangleSquare

    @protocol ShapeFactory 
    - (id<Shape>)shapeWithId:(NSString *)Id;
    @end
      
    @interface CircleFactory : NSObject <ShapeFactory>
    @end
    @implementation CircleFactory
    - (Circle *)shapeWithId:(NSString *)Id{
        Circle *circle = [Circle new];
        circle.Id = Id;
        return circle;
    }
    
    @end
      
    @interface RectangleFactory : NSObject <ShapeFactory>
    
    @end
    @implementation RectangleFactory
    - (id<Shape>)shapeWithId:(NSString *)Id{
        Rectangle *rectangle = [Rectangle new];
        rectangle.Id = Id;
        return rectangle;
    }
    @end
      
    @interface SquareFactory : NSObject <ShapeFactory>
    
    @end
    @implementation SquareFactory
    - (id<Shape>)shapeWithId:(NSString *)Id{
        Square *square = [Square new];
        square.Id = Id;
        return square;
    }
    
    
  2. 执行方法为:- (id<Shape>)loadShapeWithFactory:(id<ShapeFactory>)factory

    - (id<Shape>)loadShapeWithId:(NSString *)Id Factory:(ShapeFactory *)factory{
      return [factory shapeWithId:Id];
    }
    
  1. 通过传入不同的 Factory ,获得不同类型的 Shape 。例如:

    [self loadShapeWithId:@"2" Factory:[CircleFactory new]];
    

简单工厂方法

    在简单工厂中,可以根据参数的不同返回不同类的实例。简单工厂专门定义一个 Factory 类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。例如,删除上面的各个工厂,统一由 ShapeFactroy类根据遵守Shape 类型的类名反射创建子类的实例。

@interface ShapeFactory : NSObject

+ (id<Shape>)shapeWithId:(NSString *)Id Type:(NSString *)type;

@end
@implementation ShapeFactory
+ (id<Shape>)shapeWithId:(NSString *)Id Type:(NSString *)type{
    Class class =  NSClassFromString(type);
    if ([class conformsToProtocol:@protocol(Shape)]) {
        id <Shape>object = [class new];
        object.Id = Id;
        return object;
    }
    return  nil;
}
@end

可以将简单工厂看为工厂方法模式的一个特例,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。

总结

    工厂方法是面向对象软件设计中应用非常普遍的设计模式。工厂方法从代码中消除了对应用程序特有类的耦合。代码只需要处理 <Product> 抽象接口,所以同一代码得到复用,在应用程序中与用户定义的任何 ConcreteProduct 实体类一起工作。

相关文章

网友评论

      本文标题:iOS 设计模式的应用 ② 工厂方法

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