开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2005

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 2105|回复: 15

[凉鞋同学] Unity 游戏框架搭建 (十三) 无需继承的单例的模板

[复制链接]  [移动端链接]
排名
2762
昨日变化

28

主题

328

帖子

1589

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
46
蛮牛币
1753
威望
0
注册时间
2016-5-17
在线时间
489 小时
最后登录
2017-12-11

专栏作家

QQ
发表于 2016-11-26 18:07:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 liangxiegame 于 2016-11-26 18:08 编辑

  之前的文章中介绍的Unity 游戏框架搭建(二) 单例的模板 http://www.manew.com/thread-89635-1-1.html
和Unity游戏框架搭建(三) MonoBehaviour单例的模板http://www.manew.com/thread-89636-1-1.html有一些问题
存在的问题:
  • 只要继承了单例的模板就无法再继承其他的类。
  虽然单例继承其他类是比较脏的设计,但是难免会遇到不得不继承的时候。没有最好的设计,只有最合适的设计。
解决方案:
  • 首先实现单例的类从使用方式上应该不变,还是

[C#] 纯文本查看 复制代码
XXX.Instance.ABCFunc()
之前的单利的模板代码如下所示:

[C#] 纯文本查看 复制代码
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Reflection;

/// <summary>
/// 1.泛型
/// 2.反射
/// 3.抽象类
/// 4.命名空间
/// </summary>
namespace QFramework {  
    public abstract class QSingleton<T> where T : QSingleton<T>
    {
        protected static T mInstance = null;

        protected QSingleton()
        {
        }

        public static T Instance
        {

            get {
                if (mInstance == null) {
                    // 先获取所有非public的构造方法
                    ConstructorInfo[] ctors = typeof(T).GetConstructors (BindingFlags.Instance | BindingFlags.NonPublic);
                    // 从ctors中获取无参的构造方法
                    ConstructorInfo ctor = Array.Find (ctors, c => c.GetParameters ().Length == 0);
                    if (ctor == null)
                        throw new Exception ("Non-public ctor() not found!");
                    // 调用构造方法
                    mInstance = ctor.Invoke (null) as T;
                }

                return mInstance;
            }
        }

        public void Dispose()
        {
            mInstance = null;
        }
    }
}

按照以前的方式,如果想实现一个单例的代码应该是这样的:

[C#] 纯文本查看 复制代码
using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : QSingleton<XXXManager> {  
    private XXXManager() {
        // to do ...
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

如果我想XXXManager继承一个BaseManager代码就变成这样了

[C#] 纯文本查看 复制代码
using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : BaseManager {  
    private XXXManager() {
        // to do ...
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

这样这个类就不是单例了,怎么办?
答案是通过C#的属性。

[C#] 纯文本查看 复制代码
using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : BaseManager {  
    private XXXManager() {
        // to do ...
    }
    public static XXXManager Instance {
        get {
            return QSingletonComponent<XXXManager>.Instance;
        }
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

好了,又看到陌生的东西了,QSingletonComponent是什么?
和之前的单例的模板很相似,贴上代码自己品吧...

[C#] 纯文本查看 复制代码
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Reflection;

/// <summary>
///    组合方式实现单例子
/// </summary>
namespace QFramework {

    /// <summary>
    /// class是引用类型
    /// </summary>
    public class QSingletonComponent<T> where T : class
    {
        protected static T mInstance = null;

        public static T Instance
        {

            get {
                if (mInstance == null) {
                    // 先获取所有非public的构造方法
                    ConstructorInfo[] ctors = typeof(T).GetConstructors (BindingFlags.Instance | BindingFlags.NonPublic);
                    // 从ctors中获取无参的构造方法
                    ConstructorInfo ctor = Array.Find (ctors, c => c.GetParameters ().Length == 0);
                    if (ctor == null)
                        throw new Exception ("Non-public ctor() not found!");
                    // 调用构造方法
                    mInstance = ctor.Invoke (null) as T;
                }

                return mInstance;
            }
        }

        public static void Dispose()
        {
            mInstance = null;
        }
    }
}

这样无法继承的问题就解决啦。
缺点是:相比于QSingleton,QSingletonComponent在使用时候多了一次函数调用,不过做中小型项目应该可以应付了。
介绍完毕,睡觉了。。。

附:我的框架地址:https://github.com/liangxiegame/QFramework
转载请注明地址:凉鞋的笔记 liangxiegame.com

评分

参与人数 2鲜花 +10 收起 理由
一剑飙血 + 5 赞一个!
yhy137084 + 5 赞一个!

查看全部评分


回复

使用道具 举报

4四处流浪
336/500
排名
6291
昨日变化
2

1

主题

52

帖子

336

积分

Rank: 4

UID
15600
好友
0
蛮牛币
380
威望
0
注册时间
2014-2-25
在线时间
117 小时
最后登录
2017-11-2
发表于 2016-11-28 09:45:24 | 显示全部楼层
沙发,学习了~{:90:}{:90:}{:90:}{:90:}{:90:}

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1193/1500
排名
1386
昨日变化
2

1

主题

128

帖子

1193

积分

Rank: 6Rank: 6Rank: 6

UID
10743
好友
0
蛮牛币
1442
威望
0
注册时间
2013-12-20
在线时间
342 小时
最后登录
2017-11-3
发表于 2016-11-28 10:10:07 | 显示全部楼层
这不能算是严格的单例,这只能是基于约定的单例使用,但无法阻止其他开发人员直接调用目标类的无参构造函数。
[发帖际遇]: 狂飙的若羽 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
279
昨日变化
1

24

主题

407

帖子

3106

积分

Rank: 9Rank: 9Rank: 9

UID
10602
好友
15
蛮牛币
6320
威望
0
注册时间
2013-12-18
在线时间
885 小时
最后登录
2017-12-8

专栏作家认证开发者

发表于 2016-11-28 10:11:53 | 显示全部楼层
我一直关注你的框架,关于单例的东西,我之前也用过很多,其实想想,全局只要一个或者少数几个就好了,其他的都在这个单例类里面new一下就好了,这样也方便管理,单例多了,有时候,找起来也是麻烦事,也算是个人一点经验之谈

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1193/1500
排名
1386
昨日变化
2

1

主题

128

帖子

1193

积分

Rank: 6Rank: 6Rank: 6

UID
10743
好友
0
蛮牛币
1442
威望
0
注册时间
2013-12-20
在线时间
342 小时
最后登录
2017-11-3
发表于 2016-11-28 10:13:22 | 显示全部楼层
抱歉,刚才没有看仔细,是通过反射获取私有构造来做的。
但子类需要都实现一个私有的构造函数,可以理解为省略了私有静态单例字段和公有静态属性的相关代码。

值得参考,赞一个。

回复 支持 反对

使用道具 举报

7日久生情
2021/5000
排名
627
昨日变化

1

主题

532

帖子

2021

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
111260
好友
0
蛮牛币
7317
威望
0
注册时间
2015-6-30
在线时间
344 小时
最后登录
2017-12-4
发表于 2016-11-28 10:14:58 | 显示全部楼层
谢谢分享!

回复

使用道具 举报

排名
2537
昨日变化
2

5

主题

58

帖子

823

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
146655
好友
1
蛮牛币
1310
威望
0
注册时间
2016-4-25
在线时间
302 小时
最后登录
2017-11-30
发表于 2016-11-28 10:33:52 | 显示全部楼层
感谢楼主分享!

回复

使用道具 举报

4四处流浪
439/500
排名
5715
昨日变化
10

0

主题

59

帖子

439

积分

Rank: 4

UID
8458
好友
0
蛮牛币
640
威望
0
注册时间
2013-11-19
在线时间
191 小时
最后登录
2017-12-6
发表于 2016-11-28 12:57:43 | 显示全部楼层
参考参考

回复

使用道具 举报

7日久生情
2016/5000
排名
1459
昨日变化
9

9

主题

744

帖子

2016

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
68430
好友
3
蛮牛币
7579
威望
0
注册时间
2015-1-14
在线时间
529 小时
最后登录
2017-12-11
发表于 2016-11-28 15:09:48 | 显示全部楼层
不错,不错··

回复

使用道具 举报

7日久生情
1783/5000
排名
689
昨日变化

4

主题

164

帖子

1783

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
34678
好友
1
蛮牛币
3885
威望
0
注册时间
2014-7-16
在线时间
521 小时
最后登录
2017-11-29
发表于 2016-11-28 17:59:39 | 显示全部楼层
你这几篇单例模式的帖子都看了,设计模式不错,赞一个,但是也容易误导一些刚入的行的同学,有些新同学看到如此方便,估计会在项目中添加使用,这样对于项目可能会出现不能程度的麻烦,所以一句话,单例使用要慎重,鉴于的当前项目使用,而且单例不要过多,要不不好掌控,跟C#没有继承C++的多态一样,多了反而更繁琐。单例模式益用于中小型项目,而且不宜繁多。(个人意见)

回复 支持 反对

使用道具 举报

4四处流浪
433/500
排名
9551
昨日变化
4

0

主题

244

帖子

433

积分

Rank: 4

UID
146677
好友
8
蛮牛币
1974
威望
0
注册时间
2016-4-25
在线时间
101 小时
最后登录
2017-12-11
QQ
发表于 2016-11-28 20:15:39 | 显示全部楼层
不错的东西,顶一下,加油
[发帖际遇]: LiuBen 被钱袋砸中进医院,看病花了 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
1871/5000
排名
439
昨日变化

0

主题

70

帖子

1871

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
57557
好友
1
蛮牛币
4720
威望
0
注册时间
2014-11-25
在线时间
476 小时
最后登录
2017-5-18
QQ
发表于 2016-11-28 20:20:05 | 显示全部楼层
何必这么复杂,你让BaseManager继承单例,xxxManager继承BaseManager不就行了

回复 支持 反对

使用道具 举报

排名
2762
昨日变化

28

主题

328

帖子

1589

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
46
蛮牛币
1753
威望
0
注册时间
2016-5-17
在线时间
489 小时
最后登录
2017-12-11

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:39:56 | 显示全部楼层
livin 发表于 2016-11-28 10:11
我一直关注你的框架,关于单例的东西,我之前也用过很多,其实想想,全局只要一个或者少数几个就好了,其他 ...

谢谢建议

回复 支持 反对

使用道具 举报

排名
2762
昨日变化

28

主题

328

帖子

1589

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
46
蛮牛币
1753
威望
0
注册时间
2016-5-17
在线时间
489 小时
最后登录
2017-12-11

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:40:55 | 显示全部楼层
扯蛋超神 发表于 2016-11-28 20:20
何必这么复杂,你让BaseManager继承单例,xxxManager继承BaseManager不就行了

有道理,

回复 支持 反对

使用道具 举报

排名
2762
昨日变化

28

主题

328

帖子

1589

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
46
蛮牛币
1753
威望
0
注册时间
2016-5-17
在线时间
489 小时
最后登录
2017-12-11

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:41:56 | 显示全部楼层
玄石流星 发表于 2016-11-28 17:59
你这几篇单例模式的帖子都看了,设计模式不错,赞一个,但是也容易误导一些刚入的行的同学,有些新同学看到 ...

谢谢建议,新同学看到你的建议应该会慎用的,哈哈哈

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表