2012-05-08 12 views
5

Wdrożyłem wzór fabryczny, jak poniżej.Zrozumienie wzoru fabrycznego

Ponieważ jednak poszczególne zajęcia są publiczne, nic nie stoi na przeszkodzie, aby ktoś je bezpośrednio stworzył.

Czy to prawda? W jaki sposób zapewnić, że konkretne klasy są tworzone tylko przez 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"; 
     } 
    } 
} 

realizacja Fabryka

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(); 
     } 
    } 

} 

główna

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

Jaki jest faktyczny problem, który próbujesz rozwiązać? – Steven

+3

Czasami zastanawiam się, czy byłoby łatwiej dla wszystkich, gdyby ludzie pisali pytania w ich ojczystym języku, a ktoś z dobrym angielskim je przetłumaczył. – SimpleVar

+1

Odnosi się do tego, że obecne definicje klas pozwolą komuś stworzyć konkretne źródła danych bezpośrednio, a nie tylko przez fabrykę. –

Odpowiedz

6

Tak, twoja intuicja tutaj jest prawidłowa; jeśli chcesz ograniczyć konstrukcję swojej klasy CSVDataSourceFactory, masz błędne modyfikatory dostępu.

Jednak to nie modyfikator dostępu klasy, którą należy naprawić, to modyfikator dostępu dla konstruktora . Należy oznaczyć domyślny konstruktor internal, aby tylko inne klasy w zespole mogły je konstruować. Będziesz oczywiście musiał egzekwować własne zasady w ramach tego zgromadzenia, ale skoro masz pełną kontrolę nad tym kodem, nie powinno to stanowić problemu.

+4

Należy to odnotować w prostych słowach: Umieść wszystkie klasy Fabryki i Fabryki w tym samym projekcie i nie pozwól, aby cokolwiek innego było w tym projekcie. – SimpleVar

+0

To na pewno mi pomogło. Czy chciałbyś wiedzieć, jaka jest standardowa forma wzoru fabrycznego w odniesieniu do specyfikacji dostępu? – sameer

+1

Istnieje kilka różnych stylów, w zależności od potrzeb. To, co masz nie jest rzadkością, po "ukryciu" konstruktorów dla konkretnych klas. Inny typowy wzór jest podany w odpowiedzi @ Servy'ego: spraw, aby twoje konkretne klasy były "wewnętrzne", ale zaimplementuj "publiczny interfejs", który powraca twoja fabryka. WCF używa odmiany tego, z klasami "protected" zagnieżdżonymi wewnątrz samej klasy fabryki (np. 'HttpChannelFactory.CreateChannel()' zwraca 'nowy HttpChannelFactory.HttpRequestChannel()') Mam post na blogu w przygotowaniu na ten temat , ale niestety jest kilka tygodni. –

2

Jeśli chcesz wiedzieć, jak uniemożliwić użytkownikom tworzenie instancji źródeł danych, możesz to zrobić za pomocą interfejsów. Utwórz interfejs dla każdego źródła danych ze wszystkimi metodami, które chcesz ujawnić. Ustaw klasę jako wewnętrzną lub prywatną klasę wewnętrzną fabryki (zazwyczaj jest to odpowiednia wewnętrzna) i publiczny interfejs.

Jeśli pytanie nie brzmi, jak powstrzymać ludzi od tworzenia instancji, ale jeśli tak, to bardziej subiektywna odpowiedź. Jest kilka rzeczy do rozważenia:

  1. Jakie są konsekwencje pomijania przez kogoś czynnika i stworzenia własnego źródła danych? Nic złego? Słabsza wydajność? Poważne naruszenie bezpieczeństwa? Jeśli tylko strzelają sobie w stopę albo nic nie ranią, może nie musisz się martwić, aby ich powstrzymać.
  2. Jak trudno jest je zatrzymać? Czy chcesz uniemożliwić im korzystanie z refleksji w celu uzyskania dostępu do podstawowej klasy? Czy użycie warstwy interfejsu jest wystarczające?
  3. Jak wiarygodni są twoi użytkownicy? Czy jest to tylko wewnętrzna aplikacja do użytku własnego lub do użytku w swoim zespole? Czy jest wysyłany do tysięcy innych osób? Mała aplikacja do użytku wewnętrznego może nie przeszkadzać, na dużą skalę trzeba założyć, że istnieją naprawdę złośliwi lub nieświadomi użytkownicy, a to, co wyeksponujesz, będzie miało znaczący wpływ. Ważna jest także ogólna poprawa użyteczności, ponieważ baza użytkowników rośnie.