美文网首页
原型模式和单例模式

原型模式和单例模式

作者: 闹鬼的金矿 | 来源:发表于2021-11-22 20:45 被阅读0次

    原型模式和单例模式相对来说比较容易理解,篇幅不多,所以放到一起说。

    原型模式主要是为了简化对象的初始化代码,通过合理的封装,来减少调用方的代码量。通常情况下,Objective-C通过NSCopy协议来实现,类型需要实现一个copy方法,会这样写:

    - (Student *)copy
    {
        //创建对象
        Student *s = [[Student alloc] init];
        //初始化属性
        s.cls = self.cls;
        s.grade = self.grade;
        return s;
    }
    // 使用copy方法创建一个对象
    Student *s = [[Student alloc] init];
    Student *copyS = [s copy];
    

    如果Student仅仅继承与NSObject,感觉问题不大。如果情况再复杂一点,Student继承于People。这个时候就需要考虑基类People的属性如何进行初始化,同样如过Sutdent还有子类,子类copy方法中也需要考虑People属性如何初始化。

    简单处理:

    - (Student *)copy
    {
            //创建对象
        Sutdent *s = [[Student alloc] init];
        //初始化父类的属性
        s.name = self.name;
        s.age = self.age;
        //初始化自己的属性
        //......//
        return s;
    }
    

    这样做是可以完成任务,但是还存在一些问题: 每次实现copy方法都需要初始化父类的属性,也就是需要知道父类和父类的父类有什么属性,要去翻父类的代码才能知道,实现起来就比较麻烦。更好的方式是,每个类只需要负责自己的属性初始化,比如:

    //People.m
    - (void)setup:(People *)p
    {
        self.name = p.name;
        self.age = p.age;
    }
    
    - (void)copy
    {
        People *p = [[People alloc] init];
        [p setup:self];
        return p;
    }
    
    //Student.m
    - (void)setup:(Student *)s
    {
        [super setup:s];
        self.class = s.class;
        self.grade = s.grade
    }
    
    - (void)copy
    {
       Student *s = [[Student alloc] init];
       [s setup:self];
       return s;
    }
    
    
    

    这种方式就简单得多,子类每次实现copy方法重点在于实现setup方法。在setup方法中,父类的属性初始化通过
    调用[super setup]完成,不需要子类了解父类有哪些属性,只需要实现自己的属性初始化即可。其实现在用到了模板方法,在这个例子中就是setup方法。模板方法用的其实挺多的,像经常遇到的ViewController声明周期那几个方法就是,平时开发中应该没少重写这几个方法。

    总结一下现在这种设计的结构:

    原型模式.png

    接下来接着说单例模式

    单例模式在实际开发中也是经常会遇到:

    class Single {
        
        let name: String
        let id: Int
        
        static let instance = Single()
        
        private init() {
            self.name = "123"
            self.id = 123
        }
        
    }
    

    swift 好像这就结束了,let 定义的属性就是线程安全的。如果是Objective-C,可以考虑使用dispatch_once处理多线程问题。另外如果想绝对保证单例,需要在alloc中去处理多线程的情况:

    + (instancetype)allocWithZone:(struct _NSZone *)zone {
        
        if (_instance == nil) {
            static dispatch_once_t onceToken;
            
            dispatch_once(&onceToken, ^{
                _instance = [super allocWithZone:zone];
            });
        }
        
        return _instance;
    }
    
    - (instancetype)init {
        static dispatch_once_t onceToken;
        
        dispatch_once(&onceToken, ^{
            _instance = [super init];
            [_instance setup];
        });
        
        return _instance;
    }
    

    Reference: Dive into design patterns

    相关文章

      网友评论

          本文标题:原型模式和单例模式

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