zoukankan      html  css  js  c++  java
  • 大话设计模式之原型模式

    原型模式

    何为原型模式

    使用原型模式实例创建对象的种类,并通过复制这个原型创建新的对象

    客户端知道抽象Prototype类,在运行时,抽象Prototype子类的任何对象都可以案客户端的意愿被复制,因此,无需手工创建就可以制造同一类的多个实例。

    何时使用原型模式

    需要创建的对象应独立于其类型与创建方式

    要实例化的类是在运行时决定的

    不想要与产品层次相对应的工厂层次

    不同类的实例间的差异仅是状态的若干组合,因此复制相应数量的原型比手工实例化更加方便

    类容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修噶会更加容易

    如:有多相关的类,其行为略有不同,而且主要差异在于内部属性,如名称,图像等

      需要使用组合(树形)对象作为其他东西的基础,例如,在使用组合对象作为组件来构建另一个组合的对象

    注意

    有个使用原型对象的常见误解,原型对象是典型对象,从不实际使用,这一误解专注于实现次模式的一种特定方式,从功能的角度来看,不管什么对象,只要复制自身比手工要好,都可以是原型对象

    深复制和浅复制

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            //只要是拷贝出来的额对象,拷贝出来的对象中的内容和以前对象中的内容一致
            //“一般”情况下拷贝会生成一个新的对象
            //为什么会产生一个新的对象 1.因为拷贝要求修改原来的对象不能影响到拷贝出来的对象
            //修改拷贝出来的对象也不能影响到原来的对象,所以需要生成一个新的对象
            //2.由于以前的对象是一个不可变的对象,而是通过mutableCopy拷贝出来的对象必须是一个可变的对象,所以必须生成一个新的对象
            //会生成新的一个新的对象
        /*    //为什么会产生新的对象,1.因为拷贝
            NSString *scrStr=@"qll";
            NSMutableArray *copystr=[scrStr mutableCopy];
            NSLog(@"scrStr=%@,copyStr=%@",scrStr,copystr);*/
            
             //会生成新的一个新的对象
         /*   NSMutableString *srcStr=[NSMutableString stringWithFormat:@"qll"];
            NSMutableString *copyStr=[srcStr mutableCopy];
            [srcStr appendString:@" COOL"];
            NSLog(@"srcStr=%@",srcStr);
            NSLog(@"copyStr=%@",copyStr);*/
            
             //会生成新的一个新的对象
         /*   NSMutableString *srcStr=[NSMutableString stringWithFormat:@"all"];
            NSString *copyStr=[srcStr copy];
            [srcStr appendString:@" cool"];
            
            NSLog(@"scrStr=%@,copyStr=%@",srcStr,copyStr);*/
            
            //没有生成新的对象
            //原因:因为原来的对象是不能修改的,拷贝出来的对象一晚上不能修改的
            //既然两个都不能修改,所以永远不能影响到另外一个对象,那么已经符合要求
            //所以:OC为了对内存进行优化,就不会生成一个新的对象
            NSString *str=@"lnj";
            NSString *copyStr=[str copy];
            NSLog(@"%p, %p",str,copyStr);
            /*
                如果,没有生成新的对象,我们称之为浅拷贝,本质就是指针拷贝
                如果,生成了新的对象,我们称之为深拷贝,本质就是创建了一个新的对象,内容拷贝
             */
            
        }
        return 0;
    }

    原型模式的实现

    Cocoa Touch框架为NSObject的派生类提供了实现深复制的协议。NSObject的子类需要实现NSCopying协议机器方法----(id)copyWithZone:(NSZone *)zone。NSObject有一个实力方法叫做(id)copy。默认的copy方法调用[self copyWithZone:nil],对于采纳了NSCopying协议的子类,需要实现这个方法,否则引发异常。iOS中,这个保持新的副本对象,然后将其返回,此方法的调用要负责释放返回的对象

    代码实现

    Resume.h文件

    #import <Foundation/Foundation.h>
    
    @interface Resume : NSObject<NSCopying,NSMutableCopying>
    @property(copy,nonatomic)NSString *name;
    @property(nonatomic,copy)NSString *sex;
    @property(nonatomic,assign)int age;
    @property(copy,nonatomic)NSString *timeArea;
    @property(copy,nonatomic)NSString *company;
    @end

    Resume.m文件

    #import "Resume.h"
    
    @implementation Resume
    - (NSString *)description
    {
        return [NSString stringWithFormat:@"name=%@,age=%d,sex=%@,timeArea=%@,company=%@", _name,_age,_sex,_timeArea,_company];
    }
    -(id)copyWithZone:(NSZone *)zone{
        Resume *resume=[[[Resume class] allocWithZone:zone]init];
        resume.age=_age;
        resume.name=_name;
        resume.sex=_sex;
        resume.timeArea=_timeArea;
        resume.company=_company;
        return resume;
    }
    
    -(id)mutableCopyWithZone:(NSZone *)zone{
        return [self copyWithZone:zone];
    }
    @end

    客户端

    #import <Foundation/Foundation.h>
    #import "Resume.h"
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Resume *a=[Resume new];
            a.name=@"大鸟";     
            a.age=20;
            a.sex=@"";
            a.company=@"百度";
            a.timeArea=@"2016-2017";
            
            Resume *b=[a copy];
            b.company=@"腾讯";
            b.timeArea=@"2014-2015";
            NSLog(@"%@",a);
            NSLog(@"%@",b);
            
            
        }
        return 0;
    }

    效果

    假如有个子类继承Resume类的话,并且子类有自己特有的属性,如果其想要使用期特有的属性,需要重写

    (id)copyWithZone:(NSZone *)zone方法
    例如:子类
    workExperience.h文件
    #import "Resume.h"
    
    @interface workExperience : Resume
    @property(copy,nonatomic)NSString *workdate;
    
    @end
    workExperience.m文件
    @implementation workExperience
    - (NSString *)description
    {
        return [NSString stringWithFormat:@"name=%@,age=%d,sex=%@,timeArea=%@,company=%@,workDate=%@",[self name],[self age],[self sex],[self timeArea],[self company],_workdate];
    }
    -(id)copyWithZone:(NSZone *)zone{
        id obj=[[self class] allocWithZone:zone];
        [obj setAge:[self age]];
        [obj setName:[self name]];
        [obj setAge:[self age]];
        [obj setCompany:[self company]];
        [obj setTimeArea:[self timeArea]];
        [obj setWorkdate:_workdate];
        return obj;
    }
    @end

    客户端

     workExperience *work=[[workExperience alloc]init];
            work.name=@"大鸟";
            work.age=20;
            work.sex=@"";
            work.company=@"百度";
            work.timeArea=@"2016-2017";
            work.workdate=@"8小时";
            workExperience *work1=[work copy];
            work1.workdate=@"12小时";
            
            NSLog(@"%@",work);
            NSLog(@"%@",work1);

    总结

    当需要生成真正的副本的时候,必须要实现深复制,这样才可以对对象进行后续的操作

  • 相关阅读:
    opencv-learnopencv-Facial Landmark Detection
    【OpenCV】Learn OpenCV
    leetcode-1-TwoNums
    【c++基础】判断是否到文件末尾-eof函数
    【c++基础】int转string自动补零
    【linux】如何退出shell终端
    【机器学习算法】bagging算法
    【机器学习算法】Boostrapping算法
    【python基础】如何注释代码块
    【机器学习算法】cascade classifier级联分类器
  • 原文地址:https://www.cnblogs.com/qianLL/p/5248461.html
Copyright © 2011-2022 走看看