如何防止类在工厂外实例化

时间:2013-10-07 16:08:06

标签: c# factory

我有一个工厂。我不想允许这个工厂生产的类在工厂外实例化。如果我将它们变成抽象的,静态的,或者给它们私有构造函数,那么它们根本就不可实例化!这是语言限制还是什么?

我不想允许这个

var awcrap = new Extrude2013 (); // BAD !!!
awcrap.extrudify (); // I don't want to allow this

其余代码:

using System;

namespace testie
{
    public enum ExtrudeType { Extrude2013,  Extrude2014 }

    public interface IExtrudeStuff {
        void extrudify();
    }

    public class Extrude2013 : IExtrudeStuff { 
        public void extrudify(){ 
            Console.WriteLine ("extrudify 2013");
        }
    }

    public class Extrude2014 : IExtrudeStuff { 
        public void extrudify(){ 
            Console.WriteLine ("extrudify 2014");
        }
    }
    public static class ExtrudeFactory {
        public static IExtrudeStuff Create(ExtrudeType t) {
            switch (t) {
                case ExtrudeType.Extrude2013: return new Extrude2013 ();
                case ExtrudeType.Extrude2014: return new Extrude2014 ();
                default: return null; 
            } 
        }
    }

    class MainClass {
        public static void Main (string[] args) {
            // Now for the pretty API part
            var o = ExtrudeFactory.Create (ExtrudeType.Extrude2013);
            o.extrudify ();
            var p = ExtrudeFactory.Create (ExtrudeType.Extrude2014);
            p.extrudify ();

            var awcrap = new Extrude2013 (); // BAD !!!
            awcrap.extrudify (); // I don't want to allow this
        }
    }
}

2 个答案:

答案 0 :(得分:5)

你不能完全不允许这样做。它是否是一种语言“限制”将是一个意见问题,但有些事情你可以考虑:

  • 制作构造函数internal。这将允许声明程序集中的任何类型调用构造函数,但程序集外部没有任何内容。这意味着您在该程序集中编写的任何代码都负责调用工厂,这也意味着您无法在另一个程序集中声明该类的子类型,因为它无法调用构造函数。
  • 类似的方法是使您公开的类 abstract (或接口),然后声明internal(或甚至private作为工厂的子类,因为它永远不会在工厂之外引用)实现抽象类或接口的类型。
  • 需要一个只有工厂可以在构造函数中提供的标记。这就是DataTable类的工作原理。虽然构造函数仍然可以调用,但是用户必须传入null来获取值,并且至少很明显他们不应该这样做。

答案 1 :(得分:2)

Factory Pattern的重点是只有工厂知道如何选择和创建一个对象,它只通过一个接口而不是一个具体的类暴露实例化对象的功能。使对象的构造函数私有失败,因为Factory本身无法实例化它。

解决方案:

1-定义interface类,所有类型的Extrude20XX类都实现它,例如IExtrudeStuff

2-将Extrude20XX类包含在Factory类中作为私有嵌套类。

3-在所有IExtrude类中实现接口ExtrudeXX

4-编写一个(静态)Create (t)方法,如:

public static class ExtrudeFactory {
 public static IExtrudeStuff Create(ExtrudeType t) {
 {
   switch (t) {
       case ExtrudeType.Extrude2013: return new Extrude2013 ();
       case ExtrudeType.Extrude2014: return new Extrude2014 ();
       default: return null; 
   } 
 }
}