在上周读书笔记中,介绍了外观模式,这周的读书笔记介绍单例模式。
前言:生活中有许多东西是唯一的,地球是唯一的、太阳是唯一的。而在我们软件开发的过程中也是有很多唯一的东西,例如:服务器端的程序只能连接到一个数据库、只能有一个日志生产器;游戏世界里面也是这样的;同一时间只能允许一个关卡正在游玩、只能同时操作一个角色等等(大部分情况)。而上周笔记中提到的高级的控制面板接口也应该具有唯一性,不然你可以想象一下,如果有两个控制面板,通过两个面板进去操作的是同一个整合的子系统,就会有很大的可能造成程序混乱。所以我们应该想与控制面板类似的东西应该是具有两个特质如下:
1.同时间只存在一个对象。
2.提供一个快速获取这个对象的方法。
那么我们首先来使用最传统的方法,使用全局静态变量,代码如下:
public static class Globalobject
{
//把高级面板类对象声明为一个静态成员
}
//调用静态类里面的高级面板对象的方法
这样的写法确实很简单,但是首先很可能无意之间就直接声明了高级面板对象,再加上这个静态类的里面的高级面板对象,这样就不是唯一了,其次像全局命名的方式很容易产生重名。那么就上本次的正角儿了。
单例模式
在本书中单例模式的定义是:“确认类只有一个对象,并提供一个全局的方法来获取这个对象。”
首先单例模式需要的是程序语言要支持三个功能:
1.静态类属性
2.静态类方法
3.重新定义类建造者存取层级
单例模式实现的模拟代码如下:
namespace 单例模式
{
static class MusicVedio<T>
{
private static T m_musicVedio=default(T);
public static T m_MusicVedio
{
get
{
if (m_musicVedio == null)
{
Console.WriteLine("为这个赋值");
}
return m_musicVedio;
}
}
}
现在我们来看一下使用单例模式的优劣:
首先使用了单例模式,通过私有化成员能够让类对象只能在类成员方法中产生,再配合每一个类中只会存在一个静态成员属性,让系统可以有效的控制产生数量。这是非常大的优点,能有效避免类对象被任意产生而造成的系统错误。
同时单例模式可以避免了对象传递和引用的麻烦,完全可以不必设置参数而马上获取对象,十分的方便。所以导致现在很多的人都有单例癖,造成了滥用单例模式。
这样会浪费大量的内存,使得游戏运行时候,负担增加。
再讨论的深入一点话,单例模式使用违反了开闭原则,这个依赖的是类的实现而不是接口类,返回的对象是包含实现细节的实体类,在你需要修改这些功能的时候,你就必须修改原来的实体类,这样就容易产生bug(大部分人应该都有那种bug越改越多,新加功能导致原来就旧功能出现bug吧嘻嘻)。
浅谈优化的方法
一
做游戏的肯定不可能一次性的把所有功能都做出来,我觉得如果有这种游戏怕也是活不长的那种。(一个游戏就算才开发出来很烂,但是接受玩家意见修改后肯定也是款好游戏)所以很重要的就是更新新功能,这就对原来的代码有着非常高的质量要求。那么就要解决单例模式违反开闭原则。其实真的要让单例模式返回接口类———父类是单例模式类型,并让子类继承实现也不是没有办法,有如下两种方法实现:
1.子类向父类注册实体对象,让父类的Instance方法返回对象时候,按条件查表返回子类对象。
2.每一个子类都实现单例模式,再由父类的Instance去获得这些子类。
每个子类都实现单例模式确实可行,但第一种就不可取了。
举个例子:
比如一个IDBConnect数据库连接,服务端确实只有一个接口,但是可能连接两个不同的数据库比如mysql和oracle,这样采取子类向父类注册实体方法,再加上需要日志 ,这样两个数据库类又各自继承个子类,那么回过头来看这个特性。数据连接有了、只能有一个对象也有了、但是一个对象并不只是一个连接呀,你现在的Log日志还是IDB的对象吗?这样就产生了白马不是马的辩论。
二
从本质我们可以知道单例模式就两个重要特性:唯一的对象和方便快捷的获取对象。而我们在实际的程序开发过程应该关注的是我们的需求是什么,如果我们只是需要获取其中的一个特性,那么有几种方式可以进行设计。
这部分内容在最后总结中会进行简单介绍(毕竟这个超出单例模式而是几种设计思想了)
那么以上就是本周的读书笔记。