• 通过一个计算器的例子,了解设计模式中的工厂模式


       这个例子只是想告诉你工厂模式的概念大体是什么。但是单从这个例子来讲,用工厂模式完全是不必要和浪费时间以及加大工作量。在实际项目中,多数情况下我们不会写一个如此简单的计算器,即使写,也不会运用工厂模式。

     

    计算器实例方法声明

    @interface ViewController : UIViewController

    {

        

        BOOL bBegin;

        BOOL backOpen;

        BOOL cptOpen;

        BOOL secOpen;

        

        double fstOperand;

        double sumOperand;

        

       NSString *operator;

    }

     

    @property (strong, nonatomic) IBOutlet UITextField *display;

    @property (strong, nonatomic) IBOutlet UILabel *showSpecial;

    @property (strong, nonatomic) IBOutlet UILabel *showFoperator;

     

     

    /**

     *  初始化清屏方法

     */

    -(void)clearDisplay;

    /**

     *  回退方法

     */

    -(void)backSpace;

    /**

     *  双操作数运算方法声明

     */

    -(void)inputDoubleOperation:(NSString *)dbopt;

    -(void)inputSingleOperator: (NSString *)sgopt; // 单操作数运算方法声明

     

    /**

     *  增加。方法声明

     */

    -(void)addDot;

    /**

     *  增加正负号方法声明

     */

    -(void)addSign;

    /**

     *  数字输入方法声明

     */

    -(void)inputNumber:(NSString *)nbstr;

    /**

     *  按键管理事件声明

     */

    - (IBAction)btnClicked:(id)sender;

     

    @end

     

     

    类实现

    @interface ViewController ()

     

    @end

     

    @implementation ViewController

     

     

    - (void)viewDidLoad

    {

        _display.text = @"";

        _showSpecial.text = @"";

        _showFoperator.text = @"";

        operator = @"=";

     

        fstOperand = 0;

        sumOperand = 0;

        bBegin = YES;

        cptOpen = NO;

        secOpen = NO;

    }

     

    - (void)didReceiveMemoryWarning

    {

        [super didReceiveMemoryWarning];

        

    }

     

    - (IBAction)btnClicked:(id)sender

    {

        UIButton *btn = (UIButton *)sender;

        NSInteger tag = btn.tag;

        

        switch (tag) {

            case clearBtn:

                [self clearDisplay];

                break;

            case backBtn:

                [self backSpace];

                break;

          

            case plusBtn: // +    3

            case subBtn: // -    4

            case mulBtn: // x    5

            case divBtn: // ÷    6

       

            case equalBtn: // =    9

     

                [self inputDoubleOperation:btn.titleLabel.text];

                break;

            case dotBtn:

                [self addDot];

                break;

            case signBtn:

                [self addSign];

                break;

             //数字分支

            default:

                [self inputNumber:btn.titleLabel.text];

                break;

        }

    }

    -(void)clearDisplay

    {

        _display.text = @"";

        _showFoperator.text = @"C";

        operator = @"=";

        fstOperand = 0;

        sumOperand = 0;

        bBegin = YES;

        cptOpen = NO;

    }

    -(void)backSpace

    {

        _showFoperator.text = @"←";

        

        if (backOpen)

        {

            NSLog(@"回退回退回退%d",backOpen);

            if (_display.text.length == 1)

            {

                _display.text = @"";

            }

            else if (![_display.text isEqualToString:@""])

            {

                _display.text = [_display.text substringToIndex:_display.text.length -1];

            }

        }

    }

    -(void)addDot

    {

        _showFoperator.text = @".";

        

        if(![_display.text isEqualToString:@""] && ![_display.text isEqualToString:@"-"])

        {

            NSString *currentStr = _display.text;

            BOOL notDot = ([_display.text rangeOfString:@"."].location == NSNotFound);

            if (notDot)

            {

                currentStr= [currentStr stringByAppendingString:@"."];

                _display.text= currentStr;

            }else{

                _display.text= currentStr;

            }

        }

    }

    -(void)addSign

    {

        _showFoperator.text = @"+/-";

        

        if(![_display.text isEqualToString:@""] && ![_display.text isEqualToString:@"0"] && ![_display.text isEqualToString:@"-"])

        {

            double number = [_display.text doubleValue];

            number = number*(-1);

            _display.text= [NSString stringWithFormat:@"%g",number];

            

            if(bBegin)

            {

                sumOperand = number;

            }

        }    

     

    }

    -(void)inputNumber:(NSString *)nbstr

    {

        backOpen = YES;

        cptOpen = NO;

        NSLog(@"输入数字的时候%d",backOpen);

        if(bBegin)

        {

            _showFoperator.text = @"";

            _display.text = nbstr;

        }

        else

        {

            _display.text = [_display.text stringByAppendingString:nbstr];

        }

        bBegin = NO;

    }

    -(void)inputDoubleOperation:(NSString *)dbopt

    {

        _showFoperator.text = dbopt;

        backOpen = NO;

        NSLog(@"点击双操作符时的时候%d",backOpen);

        if(![_display.text isEqualToString:@""])

        {

            fstOperand = [_display.text doubleValue];

            

            if(bBegin)

            {

                operator = dbopt;

            }

            else

            {

                if([operator isEqualToString:@"="])

                {

                    sumOperand = fstOperand;

                }

                else if([operator isEqualToString:@"+"])

                {

                    sumOperand += fstOperand;

                    _display.text = [NSString stringWithFormat:@"%g",sumOperand];

                }

                else if([operator isEqualToString:@"-"])

                {

                    sumOperand -= fstOperand;

                    _display.text = [NSString stringWithFormat:@"%g",sumOperand];

                }

                else if([operator isEqualToString:@"x"])

                {

                    sumOperand *= fstOperand;

                    _display.text = [NSString stringWithFormat:@"%g",sumOperand];

                }

                else if([operator isEqualToString:@"÷"])

                {

                    if(fstOperand!= 0)

                    {

                        sumOperand /= fstOperand;

                        _display.text = [NSString stringWithFormat:@"%g",sumOperand];

                    }

                    else

                    {

                        _display.text = @"nan";

                        operator= @"=";

                    }

                }

           

                

                bBegin= YES;

                operator= dbopt;

            }

        }

     

    }

    - (void)inputSingleOperator: (NSString *)sgopt

    {

        _showFoperator.text = sgopt;

        backOpen = NO;

        

        if(![_display.text isEqualToString:@""])

        {

            operator = sgopt;

            fstOperand = [_display.text doubleValue];

            

            if([operator isEqualToString:@"x²"])

            {

                sumOperand = pow(fstOperand , 2);

                _display.text= [NSString stringWithFormat:@"%g",sumOperand];

            }

                   else if([operator isEqualToString:@"ln"])

            {

                sumOperand = log(fstOperand);

                _display.text= [NSString stringWithFormat:@"%g",sumOperand];

            }

            else if([operator isEqualToString:@"log"])

            {

                sumOperand = log10(fstOperand);

                _display.text= [NSString stringWithFormat:@"%g",sumOperand];

            }

                   }

            bBegin = YES;

       

    }

     

     

    @end

    以下内容转载于网络,用于对工厂模式更好的理解。

    关于工厂设计模式的个人理解:就是为了创建对象的.

           一般我们在iOS的开发过程当中,经常使用alloc来创建对象,假如我们需要创建100个button对象,那么也就是我们需要alloc100次,才能实现我们的目标.或许机智的你,会说"那还不简单,写一个for循环,alloc一次不就可以了",但是实际开发过程中如果这100个button并不是创建在一个地方那你怎么办呢?你只能照本宣科的写100次alloc来解决这个问题.

          再者,如果我们创建对象完了以后,需要去给这些对象去添加一些固有的属性跟值,比喻说:"某某工厂里面的员工",那么我们也就要多些100次这样的代码,去声明他的属性了.

           如果我们在一个-(void)createObj方法,把创建的对象以及它的工厂属性写到这个方法里面去,我们是不是会把多行代码要完成的事情,通过一句代码搞定呢?

           言外之意,也就是我们可以把alloc创建一个对象写到一个方法里面去,直接调用这个方法就 可以了.这就是我对工厂方法的个人理解.

       代码结构如下:

    声明一个类:动物类

    @interface Animal:NSObject

    @proterty(nonatomic,strong) NSString *name;

    @end-(void)running;

    @interface Dog:Animal

    @end

    @interface Cat:Animal

    @end

      常见对象的工厂类:

    .h 

    @interface AnimalFactory:NSObject

    +(Dog *)createDog;

    +(Cat *)createCat;

    @end

    .m

    +(Dog *)creatDog{

    [  Dog * dog = [Dog alloc] init];

    dog.name = @"WangCai";

      return dog;

    }

    +(Cat *)createCat{

      Cat * cat = [Cat alloc]init];

        return cat;

    }

    Main.m文件里面

    Dog *dog=[AnimalFactory createDog];

     Cat *cat=[AnimalFactory createCat];

    这就是简单的工厂方法.

    现在我们创建100个对象,也就是需要把把这个方法写100次, 那么现在我们有这样的一个需求,如果我们需要把我们用工厂方法创建的对象的名字换掉呢?那么也就是说我们需要把,这个100   处地方的Dog换成Cat,这样做就很麻烦,在实际项目中面临的问题就是代码维护起来特别麻烦.举个例子,比喻说我们用到的第三方的一个框架,AFNnetWork ,如果我们再使用的过程当中,没有去建立自己的一个工具类来封装AFN,那么加入有一天,AFN升级了,改版了,甚至是api都换掉了,那么我们用到AFN的每个控制器里面关于AFN的地方都会出现各种红色的错误提示,就像横尸遍野搬的场景.

    现在,如果您使用了工厂设计模式就能很好的解决这个问题了.

    工厂方法模式是为每一个要创建的对象所在的类都相应地创建一个工厂

    代码如下

    @interface AnimalFactory:NSObject

    -(Animal*)createAnimal;

    @end;

    Dog工厂类

    @interface DogFactory:AnimalFactory;

    @implementation DogFactory

    -(Animal *)createAnimal{

    retrurn [[Dog alloc]init];

    }

    @end

    Cat工厂类

    @interface CatFactory:AnimalFactory;

    @implementation Cat Factory

    -(Animal *)createAnimal

    retrurn [[Cat alloc]init];

    }

    @end

    Main.m

    AnimalFactory *dogFactory=[[DogFactory alloc]init];

    Animal *animal1=[dogFactory createAnimal];

    [animal1 laugh];

    Animal *animal2=[dogFactory createAnimal];

    [animal2 laugh];

    …….

    Animal *animal100=[dogFactory createAnimal];

    [animal100 laugh];

    这样话如果要把100个Dog改为Cat的话,只需要吧DogFactory改为CatFactory就可以了

    但是需要注意的是:

    1.使用工厂方法的对象都必须继承同一个父类

    2.要创建的对象在100个地方的类必须一样

    以上这些方法,纯属于个人感悟.如果有不对的地方,希望大家及时提出,我好更正.



    文/Ruo兮(简书作者)
    原文链接:http://www.jianshu.com/p/9a7168acf606
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 相关阅读:
    Java和.NET(C#)的开发用到的技术对比总结
    Sql 调优总结
    10分钟开发 GPS 应用,了解一下
    windows 命令行操作 Mysql 数据库
    【C# 复习总结】类、继承和接口
    【C#复习总结】探究各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字
    【C#复习总结】析构函数
    【C#复习总结】垃圾回收机制(GC)2
    【C#复习总结】垃圾回收机制(GC)1
    设计原则总结
  • 原文地址:https://www.cnblogs.com/wlqh/p/5361778.html
Copyright © 2020-2023  润新知