单例模式的进化——虚拟单例

来源:互联网 发布:开源网络爬虫工具 编辑:程序博客网 时间:2024/06/10 11:16

转载请注明出处:http://www.flycent.com.cn/new_articel.aspx?id=164&category_id=51

单例模式的进化——虚拟单例


    单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。单例模式由于它的特殊性,带来了许多优点,以至于在开发中被广泛使用。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。


    但是同样的,单例模式也存在一些缺点,比如不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态,而单例对象一般都是有自身来持有这个类的引用,销毁比较困难。另外,当单例在项目中被大量使用时,单例的统一调度和管理就变得相当困难,很容易引起混乱。 

    比如在近期的云享移动端的项目中,使用了较多的单例类来进行数据的管理,比如用于保存当前用户信息以供各个应用场景使用的类等等。但是当用户登出系统更换账号登录时,用户的信息发生了改变,这时候就需要更新对应的单例对象的信息,以适应新的数据环境。如果程序中只有这一个单例类,那么这个操作会很轻松。但是现实情况中肯定有很多个单例类,并且不同模块可能由不同的开发人员维护,很容易出现信息不对等,遗漏了对其它开发人员创建的单例对象的数据更新逻辑,从而导致数据的混乱。

    于是便有了这个折中的想法,暂且叫它“虚拟单例”吧。虚拟单例的使命,首先是需要保证单例模式原有的优点不丢失,另外要设法解决上面遇到的问题。那么什么叫虚拟单例呢?顾名思义,这个单例并不是一个真的单例,它也是一个可以被多次实例化的类,严格意义上来讲并不能算作是单例。但是我们可以通过一些机制来限制它,使他可以表现得和真的单例一样,保证它在某个特定的逻辑域内是固定并且唯一的,而在逻辑场景转变时可以丢弃原先的虚拟单例对象,在转变场景后的首次访问时创建一个新的对象,来应对新的情景。


    那么应该怎么做呢?我的想法是,首先需要在项目框架下做文章,保证整个项目逻辑的框架中只有一个真实的单例对象,这个单例不与任何实际的项目的业务逻辑有关联,它负责所有虚拟单例的统一调度与管理,就叫它单例中心吧。然后所有的虚拟单例类需要继承与同一个虚拟基类,这个基类不会实例化实际的对象,它只是所有的虚拟单例类可以进行统一管理和调度的保障。基类需要实现三个关键逻辑:虚拟单例的注册、访问和重载。

    1、注册,当每个虚拟单例对象被实例化之后,都要向单例中心进行注册。单例中心通过虚拟单例的类名来保持对这个对象的引用。可以通过Key-Value的模式实现,称之为单例注册表。

    2、访问,虚拟单例被访问时会首先向单例中心询问对象是否已经被注册,如果对象已经被注册,则返回注册的对象,否则创建新对象,向单例中心注册后返回该对象,从而保证虚拟单例的唯一性。

    3、重载,重载有两种方式,暂且称为强重载与弱重载吧。

        所谓强重载,即在场景发生转变时,向单例中心发送消息,告知需要重载所有单例,这时候单例中心便释放对所有单例对象的引用并清空单例注册表。从而在虚拟单例再次被访问时便需要重新实例化。使用这种方式时,需要单例的实例化过程具有灵活性,能根据当前逻辑场景来生成不同的数据。

        所谓弱重载,即在场景发生转变,单例中心收到重载消息时,不会释放所有虚拟单例对象的引用,也不会清空单例注册表,而只是将重载指令发送给注册表中的所有的虚拟单例对象,由各个虚拟单例对象自己来完成重载数据的过程。使用这种方式要求虚拟单例自己来实现根据当前逻辑场景重载数据的逻辑。

    以上只是个人在项目维护时冒出来的一些想法,下一步将是将其在飞讯iOS内部框架上实现,在实际项目中检验它的可靠性和实用性。由于个人技术水平的局限,以上设计若存在不妥之处,还望高人指点。(错别字请忽略)


原创文章,转载请注明出处:http://www.flycent.com.cn/new_articel.aspx?id=164&category_id=51

0 0
原创粉丝点击