工厂模式

作者: Corbin___ | 来源:发表于2019-06-02 23:41 被阅读2次

    简单工厂模式,工厂方法模式,抽象工厂模式都属于创建型的设计模式

    简单工厂模式

    首先有一个需求,客户端需要一个计算类,这个计算类有加减乘除功能,请问你怎么设计?

    最简单直接写一个计算类,实现加减乘除的接口,客户端调用传参进来,给你返回结果就行了

    这样设计的扩展性不高,比如以后需要再加开根号,加法做下特殊处理的等一堆需求进来后,这个计算类就会变得非常的臃肿,不满足开闭原则,对修改关闭,对扩展开放

    有任何需求都需要在计算类中做修改,这样可能影响到以前的代码,所以开闭原则就是希望对修改关闭的。那如果做到对扩展开放,就是通过继承的方式

    第二种做法就是抽象一个基类计算类,计算类定好虚函数,比如result函数等,创建加减乘除四个子类,都实现result方法,这样有利于以后的扩展,比如需要开根号计算,就再创建一个开根号子类,实现result方法,这样不会修改原本的代码,但是将功能扩展出来了

    客户端调用

    
    Add *add = [[Add alloc] init];
    [add result];
    
    Sub *sub = [[Sub alloc] init];
    [sub result];
    
    Multi *multi = [[Multi alloc] init];
    [multi result];
    
    Division *division = [[Division alloc] init];
    [division result];
    
    

    以后如果再添加其他算法,客户端都得认识这种算法类,客户端得写对应的子类,对于这种方式,我们可以采用简单工厂模式,将子类的创建代码,放到工厂类中,外部调用只需要告诉工厂类需要创建什么对象

    工厂类

    /// 工厂类
    @interface Factory : NSObject
    
    + (instancetype)creatWithType:(NSString *)type;
    
    @end
    
    @implementation Factory
    
    + (instancetype)creatWithType:(NSString *)type
    {
        switch (type) {
            case @"+":
                return  [[Add alloc] init];
    
                break;
            
            case @"-":
                return  [[Sub alloc] init];
    
                break;
            
            case @"*":
                return  [[Multi alloc] init];
    
                break;
            
            case @"/":
                return  [[Division alloc] init];
    
                break;
                
            default:
                return nil;
                break;
        }
    }
    
    @end
    
    

    抽象计算类

    @interface AbstractProduct : NSObject
    
    - (CGFloat)result;
    
    @end
    
    @implementation AbstractProduct
    
    - (CGFloat)result
    {
        
    }
    
    @end
    

    客户端调用

    
    AbstractProduct *p = [Factory creatWithType:@"+"];
    [p result];
    
    

    那么这样做的好处就是将代码的职责分离,工厂类负责创建对象,计算子类负责对应的需求,客户端只需要通过工厂就可以拿到想要的子类,然后通过抽象基类调虚函数,就能获取对应的结果

    但是这样还是违背了开闭原则,比如我添加一个开根号类,这时候工厂类中的if-else或switch需要对应的添加代码,这样日积夜累,工厂类会变得臃肿,再对其做修改后,影响面很大

    工厂方法模式

    工厂方法模式可以解决简单工厂方法模式违背开闭原则

    刚才我们解决计算类违背开闭原则的,就是通过计算类定义虚函数,子类实现虚函数,外部调用result方法就可以了,如果添加开根号类,一样创建子类,实现result,这样就不会修改原来的代码了

    一样的方法,原本的工厂类违背开闭原则了,那么我们创建一个抽象工厂类,定义creat虚函数,加减乘除四个工厂子类实现creat函数

    客户端调用

    
    Add *add = [FactoryAdd creat];
    Sub *sub = [FactorySub creat];
    
    

    在客户端调用上,似乎抽象工厂类没有作用,因为创建产品的还是子工厂类来创建,那么我为什么还要继承抽象工厂类?

    当然,我们可以不用继承抽象工厂类,比如FactoryAdd和FactorySub继承NSObject,定义creat方法,返回对应的产品对象,在客户端的调用,依旧跟上段代码一样,效果也一样

    那么当我们这样做后,是不是发现其实FactoryAdd和FactorySub是有共性的,他们都是负责去创建抽象计算机类的子类,那么有共性的类,不就可以抽象出一个基类吗,因此抽象工厂类就这样来了

    抽象工厂方法

    在了解抽象工厂方法之前要先说两个名词“产品族”和“产品等级结构”

    产品等级结构

    比如抽象类为电视机,子类就有小米电视机,海尔电视机,海信电视机等,那么这样就构成了一个产品等级结构

    产品等级结构

    产品族

    同一个工厂生产的,位于不同产品等级结构中的一组产品,比如手机,有华为手机,小米手机,那么小米手机和小米电视机都是一个产品族

    抽象工厂方法和工厂方法在代码上的实现是一致的,产品有产品的抽象类,工厂有工厂的抽象类,只不过,工厂方法是面向一个产品等级结构,也就是说工厂方法模式中的具体工厂类只生产一种产品,而抽象工厂方法的具体工厂方法中生产多种产品,比如一个小米工厂可以生产小米手机,小米电视

    总结

    简单工厂方法

    专门创建一个类来负责创建产品类实例,通常这个产品类都是继承于同一个基类

    这个工厂类包含了必要的判断逻辑,根据外部给定的参数,创建对应的产品类对象

    好处就是用户在使用的时候,无需关心这个产品类是怎么被创建出来的,只需要传对应的参数,就创建对应的产品对象出来了

    工厂方法模式

    工厂方法模式是在简单工厂方法的基础上,对工厂方法进行了抽象,解决了简单工厂方法中的工厂类违背开闭原则的问题;这时候的工厂类就不负责创建产品对象了,而是负责定义创建产品对象的接口或者规则,让实现接口的人(子类)去负责创建产品类对象

    实现了更加复杂的层次结构,更加适用于更加复杂的业务场景以及后续扩展

    抽象工厂模式

    当有多个产品等级结构时,就应该采用抽象工厂方法;如果只有一个产品等级结构,那么就使用工厂方法模式;如果为了快速怼业务,并且考虑到不需要太过度的去构架,那么就直接简单工厂模式

    相关文章

      网友评论

        本文标题:工厂模式

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