Singleton паттерн

Тема в разделе ".NET", создана пользователем NikSoft, 12 ноя 2006.

  1. NikSoft

    NikSoft Гость

    В моей предыдущей заметке( Single Instance Application ) было показано как строить приложение, только единичная копия которого находится в памяти в любой момент времени. Продолжим эту же тему по отношению к типу.
    Пусть нам нужен централизованный доступ к базе данных, причем необходимо иметь только один обьект класса, реализующий этот доступ. Следующий класс GetInfoFromDB решает задачу.

    Код (Text):
    using System.Data;
    using System.Data.SqlClient;

    namespace Singleton
    {
    class GetInfoFromDB
    {
    static GetInfoFromDB _instance = null;

    protected GetInfoFromDB(){ } // the constructor

    static GetInfoFromDB Instance
    {
    get
    {
    if (_instance == null) _instance = new GetInfoFromDB();
    return _instance;
    }
    }

    static SqlConnection Connection
    {
    get
    {
    return new SqlConnection("Data Source=(local);Initial Catalog=Costupdate;Integrated Security=True;");
    }
    }

    DataTable GetCategoriesFromDB()
    {
    DataSet dataSet = new DataSet();

    Connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Categories;", Connection);
    adapter.Fill(dataSet, "Categories");
    Connection.Close();

    return dataSet.Tables["Categories"];
    }

    public static DataTable GetCategories()
    {
    return Instance.GetCategoriesFromDB();
    }

    DataTable GetManufacturersFromDB()
    {
    DataSet dataSet = new DataSet();

    Connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Manufacturers;", Connection);
    adapter.Fill(dataSet, "Manufacturers");
    Connection.Close();

    return dataSet.Tables["Manufacturers"];
    }

    public static DataTable GetManufacturers()
    {
    return Instance.GetManufacturersFromDB();
    }
    }
    }
    Ввиду того, что спецификатор доступа конструктора класса – protected, доступ к классу обеспечивается только
    через статические методы GetCategories, GetManufacturers,которые являются публичными(public).
    При вызове этих методов(как, например, в следующем коде)

    Код (Text):
    dataGridView1.DataSource = new DataView(GetInfoFromDB.GetCategories());
    dataGridView2.DataSource = new DataView(GetInfoFromDB.GetManufacturers());
    происходит обращение к свойству Instance класса. Это свойство проверяет, был ли создан обьект
    класса GetInfoFromDB. Если нет, то создается обьект типа GetInfoFromDB, ссылка на который присваивается приватному статическому полю _instance. В любом случае возвращается ссылка только на один и тот же обьект типа GetInfoFromDB.
     
  2. karlito

    karlito Гость

    Для: NikSoft
    Оценка 2 за этот код.

    Код (Text):
    if (_instance == null) _instance = new GetInfoFromDB();
    return _instance;
    Данный код непотокобезопасен.

    Код (Text):
    Connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Categories;", Connection);
    adapter.Fill(dataSet, "Categories");
    Connection.Close();
    соединение гарантировано закрывать надо?

    PS:
    1. люди учатся по твоему коду и учатся неправильно, что самое страшное
    2. любой шаблон предназаначен для решения неких проблем. именно с этого надо было начинать.
    Для чего ты у себя используешь этот шаблон в коде не совсем понятно.
    3. есть некий неформальное соглашение по кодированию шаблонов. везде функционал по предоставлению Singleton объекта отдаётся клиенту через метод Instance(), а не свойство.
     
  3. eisernWolf

    eisernWolf Гость

    >>Данный код непотокобезопасен.

    А что, кто-то обещал безопасность при мультитрединге? :)

    >>через метод Instance(), а не свойство.

    get_Instance() тоже ничего себе метод ;)
     
  4. @Egot

    @Egot Гость

    public static GetInfoFromDB Instance = new GetInfoFromDB();

    будет более потокобезопасеным. Но минусом является то что инстанс объекта будет создаваться сразу при старте приложения а не при первом обращении к проперти.
     
  5. Pasha

    Pasha Гость

  6. karlito

    karlito Гость

    Решение, испытанное годами.

    Код (Text):
    internal class AddInHolder
    {
    private AddInHolder(){}

    #region Singleton

    private static volatile AddInHolder _instance = null;
    private static object _syncRoot = new object();

    internal static AddInHolder Instance()
    {
    if((_instance == null))
    {
    lock(_syncRoot)
    {
    if((_instance == null))
    {
    _instance = new AddInHolder();
    }
    }
    }
    return _instance;
    }
    #endregion
    }
    Для: Pasha
    Не надо лочить объекты без нужды - крепче спать будешь.
     
  7. Pasha

    Pasha Гость

    2 karlito: Я же дал ссылку, там есть этот вариант. И результаты тестов. Вариант с двойной проверкой работает на 1% быстрее :)
     
  8. karlito

    karlito Гость

    Для: Pasha
    Прогони этот тест на 1000 потоков одновременно. я думаю процент вырастет и намного.
     
  9. Pasha

    Pasha Гость

    Согласен, был неправ :D Проверил: 1000 потоков, каждый занят только тем, что получает значение Instance. Двойная проверка работает примерно в 2 раза быстрее. Но если потоки при этом занять еще и чем-то другим, то разница в производительности сразу исчезает.
     
Загрузка...
Похожие Темы - Singleton паттерн
  1. rrrFer
    Ответов:
    0
    Просмотров:
    435

Поделиться этой страницей