Singleton(单例)——对象创建型模式

Singleton单例——对象创建型模式

意图

保证一个类在整个应用程序域中仅有一个实例,并提供一个访问它的全局访问点。

Signleton模式的优点

1、对唯一实例的受控访问。因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。
2、缩小名空间。Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。
3、允许对操作和表示的精化。Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。
4、允许可变数据的实例。这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变。
5、比类操作更灵活。

典型应用场景

单例应用最多的地方就是读取配置文件,并在程序逻辑中通过Singleton类的实例访问配置文件的配置项。

实现要点

单例类设计的要点如下:

1、在类中定义私有(private)、静态(static)的本类对象,用于保存全局唯一实例。
2、把(默认)构造方法定义为私有(private)。
3、定义获取本类实例的静态方法或静态属性。

案例代码

通过单例模式实现封装对xml配置文件的读取操作。
xml配置文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!--工厂ID-->
  <add key="FactoryID" value="1" />
  <!--单机/网络:0为单机,1为网络-->
  <add key="NetType" value="1" />
  <!--网络服务器连接检测模式:0-网络库检测,1-Ping检测-->
  <add key="CheckConnectMode" value="1" />
  <!--网络数据库服务器IP地址-->
  <add key="NetDbServerIP" value="127.0.0.1" />
  <!--本地数据库-->
  <add key="DataSource.Local" value="DataSource1" />
  <!--本地曲线库-->
  <add key="DataSource.Curve" value="DataSource2" />
  <!--工艺回溯数据库-->
  <add key="DataSource.BackView" value="DataSource3" />
  <!--自定义设备名称,用于更新SysKeyValue表后进行界面数据更新-->
  <add key="Customer.EquipName" value="FeedingCustomer" />
  <!--机台编码-->
  <add key="EquipCode" value="01001" />
  <!--消息窗口显示模式,0-显示3秒自动关闭,1-手动关闭-->
  <add key="MessageDialogMode" value="0" />
</configuration>

Singleton类代码如下:

using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.IO;

namespace Mesnac.Basic
{
    /// <summary>
    /// 组态工程运行配置解析类
    /// </summary>
    public class RunSchema
    {
        #region 定义变量

        private string _projectPath = String.Empty;            //组态工程路径
        private string _eventConfigPath = String.Empty;        //事件处理(Action)配置文件路径
        private string _runSchemaFilePath = "RunSchema.xml";   //运行结构配置文件路径

        private Dictionary<string, string> _runSchemaDic = new Dictionary<string, string>();

        #endregion

        #region 定义属性

        public Dictionary<string, string> RunSchemaDic
        {
            get
            {
                if (_runSchemaDic.Count == 0)
                {
                    ParseFromRunSchema();
                }
                return _runSchemaDic;
            }
            private set
            {
                _runSchemaDic = value;
            }
        }
        /// <summary>
        /// 组态工程路径
        /// </summary>
        public string ProjectPath
        {
            get { return this._projectPath; }
            set { this._projectPath = value; }
        }

        /// <summary>
        /// 事件处理(Action)配置文件路径
        /// </summary>
        public string EventConfigPath
        {
            get { return this._eventConfigPath; }
            set { this._eventConfigPath = value; }
        }

        #endregion

        #region 单例模式实现

        private static RunSchema _this;     //私有静态实例,保存全局作用域中的唯一实例

        /// <summary>
        /// 静态实例属性
        /// </summary>
        public static RunSchema Instance
        {
            get
            {
                if (null == _this)
                    _this = new RunSchema();
                return _this;
            }
        }

        /// <summary>
        /// 私有构造方法
        /// </summary>
        private RunSchema()
        {
            this._runSchemaDic = new Dictionary<string, string>();
        }

        #endregion

        #region 基本信息
        public string FilePath()
        {
            return Path.Combine(this._projectPath, this._runSchemaFilePath);
        }
        #endregion

        #region 检测配置文件是否存在
        /// <summary>
        /// 检测配置文件是否存在(先检测组态工程目录,在检测事件处理(Action)配置文件路径)
        /// </summary>
        /// <returns>存在返回true,否则返回false</returns>
        public bool Exists()
        {
            string runSchemaFile = FilePath();
            string runSchemaFile2 = Path.Combine(this._eventConfigPath, this._runSchemaFilePath);
            if (File.Exists(runSchemaFile) || File.Exists(runSchemaFile2))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region 解析运行环境主配置文件RunSchema.xml
        /// <summary>
        /// 解析运行环境主配置文件RunSchema.xml
        /// </summary>
        public void ParseFromRunSchema()
        {
            try
            {
                //如果组态工程目录(MCProject)下有RunSchema文件,则首先以组态工程目录下的文件为配置文件,
                //否则以事件处理(Action)配置文件所在的目录下的RunSchema文件为准
                string runSchemaFile = FilePath();
                Dictionary<string, string> dic = new Dictionary<string, string>();
                if (!File.Exists(runSchemaFile))
                {
                    runSchemaFile = Path.Combine(this._eventConfigPath, this._runSchemaFilePath);
                }
                if (File.Exists(runSchemaFile))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(runSchemaFile);
                    XmlNodeList nodeList = doc.GetElementsByTagName("add");
                    foreach (XmlNode node in nodeList)
                    {
                        string key = node.Attributes["key"].Value;
                        if (!dic.ContainsKey(key))
                        {
                            string value = node.Attributes["value"].Value;
                            dic.Add(key, value);
                        }
                        else
                        {
                            //存在重复键
                            ICSharpCode.Core.LoggingService<RunSchema>.Error("配置文件中存在重复键的配置项,key = " + key);
                        }
                    }
                }
                else
                {
                    //配置文件不存在
                    ICSharpCode.Core.LoggingService<RunSchema>.Warn("应用程序配置文件不存在!");
                }
                this._runSchemaDic = dic;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<RunSchema>.Error(ex.Message);
                throw ex;
            }
        }
        /// <summary>
        /// 保存配置信息
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="runSchemaFile"></param>
        public void UpdateToRunSchema(Dictionary<string, string> dic)
        {
            string runSchemaFile = FilePath();
            if (dic != null && dic.Count > 0)
            {
                XmlDocument doc = new XmlDocument();
                XmlElement root = doc.CreateElement("configuration");
                foreach (string key in dic.Keys)
                {
                    XmlElement eAdd = doc.CreateElement("add");
                    XmlAttribute eAttKey = doc.CreateAttribute("key");
                    eAttKey.Value = key;
                    XmlAttribute eAttValue = doc.CreateAttribute("value");
                    eAttValue.Value = dic[key];
                    eAdd.Attributes.Append(eAttKey);
                    eAdd.Attributes.Append(eAttValue);
                    root.AppendChild(eAdd);
                }
                doc.AppendChild(root);
                doc.Save(runSchemaFile);
            }
            ParseFromRunSchema();
        }
        /// <summary>
        /// 更新配置节点至文件
        /// </summary>
        /// <param name="key">要更新的配置项</param>
        /// <param name="newValue">要更新的配置项的值</param>
        public void UpdateNodeValueToRunSchema(string key, string newValue)
        {
            try
            {
                string runSchemaFile = FilePath();
                if (File.Exists(runSchemaFile))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(runSchemaFile);
                    XmlNodeList nodeList = doc.GetElementsByTagName("add");
                    bool flag = false;
                    foreach (XmlNode node in nodeList)
                    {
                        if (node.Attributes["key"].Value == key)
                        {
                            node.Attributes["value"].Value = newValue;
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        XmlElement eAdd = doc.CreateElement("add");
                        XmlAttribute eAttKey = doc.CreateAttribute("key");
                        eAttKey.Value = key;
                        XmlAttribute eAttValue = doc.CreateAttribute("value");
                        eAttValue.Value = newValue;
                        eAdd.Attributes.Append(eAttKey);
                        eAdd.Attributes.Append(eAttValue);
                        doc.DocumentElement.AppendChild(eAdd);
                    }
                    doc.Save(runSchemaFile);
                }
                else
                {
                    //配置文件不存在
                    ICSharpCode.Core.LoggingService<RunSchema>.Warn("应用程序配置文件不存在!");
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<RunSchema>.Error(ex.Message);
                throw ex;
            }
            ParseFromRunSchema();
        }

        #endregion

        #region 获取RunSchema配置文件中配置项的值
        /// <summary>
        /// 获取RunSchema配置文件中配置项的值
        /// </summary>
        /// <param name="key">配置型</param>
        /// <param name="defaultValue">获取不到时的默认值</param>
        /// <returns>返回对应配置项的值</returns>
        public string GetConfigValue(string key, string defaultValue)
        {
            string value = string.Empty;
            if (this.RunSchemaDic.TryGetValue(key, out value))
            {
                return value;
            }
            return defaultValue;
        }

        public bool GetConfigValue(string key, bool defaultValue)
        {
            string value = GetConfigValue(key, String.Empty);
            bool result = defaultValue;
            if (bool.TryParse(value, out result))
            {
                return result;
            }
            else
            {
                return defaultValue;
            }
        }

        public int GetConfigValue(string key, int defaultValue)
        {
            string value = GetConfigValue(key, String.Empty);
            int result = defaultValue;
            if (int.TryParse(value, out result))
            {
                return result;
            }
            else
            {
                return defaultValue;
            }
        }

        #endregion

        #region 判断Schema文件是否存在

        /// <summary>
        /// 判断Schema文件是否存在
        /// </summary>
        /// <returns>存在返回true,失败返回false</returns>
        public bool IsSchemaExists()
        {
            string runSchemaFile = FilePath();
            if (File.Exists(runSchemaFile))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion
    }
}

猜你喜欢

转载自blog.csdn.net/zlbdmm/article/details/83090456