2012-05-08 44 views
5

我已經實現瞭如下的工廠模式。工廠模式瞭解

但是,由於各個類是公共的,因此沒有任何東西阻止某人直接實例化它們。

這是正確的嗎?我如何確保只通過工廠創建具體的類?

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

這對我有幫助。想知道工廠模式在訪問說明符方面的標準形式是什麼? – sameer

+1

根據您的需要,有幾種不同的款式。一旦你「隱藏」具體類的構造函數,你擁有的並不少見。在@Servy的答案中給出了另一種常見模式:使您的具體類爲「內部」,但實現您的工廠返回的「公共接口」。 WCF使用這種變體,'protected'類嵌套在工廠類中(例如'HttpChannelFactory.CreateChannel()'返回一個'new HttpChannelFactory.HttpRequestChannel()')我有一篇關於這個的博客文章,但不幸的是在幾周後。 –

2

如果你想知道如何防止人們能夠創建數據源的實例,你可以通過接口來實現。使用您希望公開的所有方法爲每個數據源創建一個接口。將類本身作爲工廠的內部或私有內部類(內部通常是合適的)並將接口公開。

如果問題不在於如何阻止人們創建實例,但如果您應該這樣做,那更多的是主觀答案。有幾件事情需要考慮:

  1. 有人繞過這個因素,並創建自己的數據源有什麼後果?沒什麼不好?性能較差?嚴重的安全違規?如果他們只是在腳下射傷或者什麼都不傷,也許你不需要費心去阻止他們。
  2. 阻止它們有多難?你是否需要阻止他們使用反射來訪問基礎類?使用界面層是否足夠?
  3. Trustworty是您的用戶?它只是一個內部應用程序,供您自己使用或供您自己的團隊使用?它被運送到成千上萬的其他人嗎?一個小型的內部使用應用程序可能不會打擾,大規模的應用程序需要假設有真正的惡意或無知的用戶,你所暴露的內容將顯着重要。隨着用戶羣的增長,改善可用性也很重要。