好了,介绍了工厂模式,我们再来学习一个新的设计模式:单例模式。单例模式是运用最为广泛的一种设计模式。那么什么是单例模式呢?简单来说,单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的共有的函数用于创建或获取它本身的静态私有对象。由此我们知道,单例模式最大的优点就是确保了实例的唯一性,当其它对象试图访问实例的副本时,都将遭到拒绝!
好,下面我们通过一个具体的例子来学习单例模式。我们知道.Net提供了用于语音合成和语音识别的类库,我们为了在自己的项目中集成语音功能,我们需要对这个类库中的方法做一些封装。你可能会说,这很简单啊,我把语音合成的初始化语句写在构造函数里,然后在全局访问它的方法不就行了。我承认这样可以,可是如果我们要在程序多处使用语音功能,你能够保证不会出现在同一时刻发声的问题吗?这是因为我们创建了多个语音合成的实例,所以,为了解决这个问题,我们使用了单例模式来解决这个问题。
下面是一个用于语音合成的类文件Speech
/// <summary>
/// 单例模式下的语音朗读类
/// </summary>
public class Speech
{
private static Speech _Instance;//私有的静态对象
private static SpeechLib.SpVoiceClass Voice;
private SpFileStream FileStream;//语音文件流对象
/// <summary>
/// 声音
/// </summary>
public int Volume
{
get{return Voice.Volume;}
set { Voice.SetVolume((ushort)value); }
}
/// <summary>
/// 速度
/// </summary>
public int Rate
{
get { return Voice.Rate; }
set { Voice.SetRate(value); }
}
/// <summary>
/// 声音录制
/// </summary>
/// <param name="type">类型</param>
/// <param name="FileName">文件路径</param>
/// <param name="Content">文本内容</param>
public void Record(SpeechAudioFormatType type,string FileName,string Content)
{
FileStream.Format.Type = SpeechAudioFormatType.SAFT22kHz16BitMono;
FileStream.Open(FileName, SpeechStreamFileMode.SSFMCreateForWrite, false);
Voice.AudioOutputStream = FileStream;
if (Content != "")
{
Voice.Speak(Content);
Voice.WaitUntilDone(-1);
FileStream.Close();
FileStream = null;
}
}
/// <summary>
/// 私有的构造函数
/// </summary>
private Speech()
{
BuildSpeech();
}
/// <summary>
/// 构建Voice的方法
/// </summary>
private void BuildSpeech()
{
if (Voice == null)
{
Voice = new SpeechLib.SpVoiceClass();
}
}
/// <summary>
/// 单例模式验证,获取私有对象的方法
/// </summary>
/// <returns></returns>
public static Speech Instance()
{
if (_Instance == null)
{
_Instance = new Speech();
}
return _Instance;
}
/// <summary>
/// 中文
/// </summary>
public static void SetChina()
{
Voice.Voice = Voice.GetVoices(string.Empty, string.Empty).Item(0);
}
/// <summary>
/// 英文
/// </summary>
public static void SetEnglish()
{
Voice.Voice = Voice.GetVoices(string.Empty, string.Empty).Item(1);
}
/// <summary>
/// 朗读
/// </summary>
/// <param name="strSpeak"></param>
private static void Speak(string strSpeak)
{
try
{
Voice.Speak(strSpeak, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
catch(Exception e)
{
throw new Exception("发生一个错误:" + e.Message);
}
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
Voice.Speak(string.Empty, SpeechLib.SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
}
/// <summary>
/// 暂停
/// </summary>
public void Pause()
{
Voice.Pause();
}
/// <summary>
/// 恢复
/// </summary>
public void Resume()
{
Voice.Resume();
}
/// <summary>
/// 中文朗读
/// </summary>
/// <param name="StrSpeak"></param>
public void SpeachInChinese(string StrSpeak)
{
SetChina();
Speak(StrSpeak);
}
/// <summary>
/// 英文朗读
/// </summary>
/// <param name="StrSpeak"></param>
public void SpeakInEnglish(string StrSpeak)
{
SetEnglish();
Speak(StrSpeak);
}
}
在具体使用时,我们使用Instance方法来获取当前的实例,你会发现,无论我们创建多少个Speech的对象,只有一个实例!