2012-05-08 2 views
5

Я реализовал заводской шаблон, как показано ниже.Factory Pattern Понимание

Однако, поскольку отдельные классы являются общедоступными, ничто не мешает кому-либо создавать их непосредственно.

Это правильно? Как я могу гарантировать, что конкретные классы создаются только через Factory?

namespace MRS.Framework 
{ 
    public abstract class DataSource 
    { 
     public override string ToString() 
     { 
      return "DataSource"; 
     } 
    } 

    public class XMLDataSource : DataSource 
    { 

    } 

    public class SqlDataSource : DataSource 
    { 

    } 

    public class CSVDataSource : DataSource 
    { 
     public int MyProperty { get; set; } 


     public override string ToString() 
     { 
      return "CSVDataSource"; 
     } 
    } 
} 

реализация Завод

namespace MRS.Framework 
{ 
    public abstract class DataSourceFactory 
    { 
     public abstract DataSource CreateDataSource(DataSourceType datasourcetype); 
    } 

    public class CSVDataSourceFactory : DataSourceFactory 
    { 
     public CSVDataSourceFactory() 
     { 

     } 
     public override DataSource CreateDataSource(DataSourceType datasourcetype) 
     { 
      return new CSVDataSource(); 
     } 
    } 


    public class XMLDataSourceFactory : DataSourceFactory 
    { 
     public override DataSource CreateDataSource(DataSourceType datasourcetype) 
     { 
      return new XMLDataSource(); 
     } 
    } 

    public class SqlDataSourceFactory : DataSourceFactory 
    { 
     public override DataSource CreateDataSource(DataSourceType datasourcetype) 
     { 
      return new SqlDataSource(); 
     } 
    } 

} 

Главная

static void Main(string[] args) 
     { 
      DataSourceFactory datasourcefactory = new CSVDataSourceFactory(); 
      CSVDataSource ds = (CSVDataSource)datasourcefactory.CreateDataSource(DataSourceType.CSVDataSource); 
      CSVDataSource myds = new CSVDataSource(); 
      Console.WriteLine(ds.ToString()); 
      Console.WriteLine(myds.ToString()); 
      Console.ReadLine(); 

     } 
+0

В чем проблема, которую вы пытаетесь решить? – Steven

+3

Иногда мне интересно, будет ли проще для всех, если люди будут писать вопросы на своем родном языке, а кто-то с хорошим английским переводом. – SimpleVar

+1

Он имеет в виду тот факт, что определения текущего класса позволят кому-то создавать конкретные источники данных напрямую, а не только через фабрику. –

ответ

6

Да, ваша интуиция здесь правильно; если вы хотите ограничить строительство своего класса CSVDataSourceFactory, тогда у вас есть модификаторы доступа.

Однако это не модификатор доступа класса, который требуется исправить, это модификатор доступа конструктора . Вы должны пометить конструктор по умолчанию internal, чтобы только другие классы в вашей сборке могли их построить. Разумеется, вы должны будете применять свои собственные правила в рамках этой сборки, но поскольку у вас есть полный контроль над этим кодом, это не должно быть проблемой.

public class XMLDataSource : DataSource 
{ 
    internal XMLDataSource() { } 
} 

public class SqlDataSource : DataSource 
{ 
    internal SqlDataSource() { } 
} 

public class CSVDataSource : DataSource 
{ 
    public int MyProperty { get; set; } 

    internal CSVDataSource() { } 

    public override string ToString() 
    { 
     return "CSVDataSource"; 
    } 
} 
+4

Это следует отметить простыми словами: Поместите все классы Factory-Classes и Factory в один и тот же проект и не позволяйте в этом проекте ничего другого. – SimpleVar

+0

Это определенно помогло мне. Хотелось бы узнать, что является стандартной формой Factory Pattern в отношении спецификаторов доступа? – sameer

+1

В зависимости от ваших потребностей существует несколько разных стилей. То, что у вас есть, не редкость, как только вы «спрячете» конструкторы для конкретных классов. Еще один общий шаблон приведен в ответе @ Servy: сделайте свои конкретные классы «внутренними», но реализуйте «открытый интерфейс», который возвращает ваш завод. WCF использует вариацию этого, причем классы 'protected' вложены внутри самого класса фабрики (например,' HttpChannelFactory.CreateChannel() 'возвращает новый HttpChannelFactory.HttpRequestChannel()'). У меня есть сообщение в блоге об этом , но, к сожалению, несколько недель. –

2

Если вы хотите знать, как предотвратить возможность людей создавать экземпляры источников данных, вы можете сделать это через интерфейсы. Создайте интерфейс для каждого источника данных со всем методом, который вы хотите открыть. Сделайте сам класс внутренним или внутренним внутренним классом фабрики (обычно это обычно подходит), а интерфейс - общедоступный.

Если вопрос заключается не в том, как остановить людей от создания экземпляров, а в случае необходимости, это более субъективный ответ. Есть несколько вещей, которые следует учитывать:

  1. Каковы последствия того, что кто-то обходит фактор и создает собственный источник данных? Ничего плохого? Более низкая производительность? Основное нарушение безопасности? Если они только стреляют в ногу или ничего не болят, возможно, вам не нужно их останавливать.
  2. Как трудно остановить их? Вам нужно, чтобы они не использовали рефлексию для доступа к базовому классу? Достаточно ли использовать интерфейсный уровень?
  3. Как Вы доверяете своим пользователям? Это просто внутреннее приложение для вашего собственного использования или для использования в вашей собственной команде? Он отправляется тысячам других людей? Небольшое приложение для внутреннего использования, возможно, не беспокоит, большой масштаб необходимо предположить, что есть действительно злонамеренные или неосведомленные пользователи, и то, что вы выставляете, будет иметь большое значение. Также важно улучшить удобство использования в целом по мере роста пользовательской базы.