10

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

我不想让这个

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
        }
    }
}
4

2 回答 2

7

你不能完全禁止这一点。是否是语言“限制”是一个见仁见智的问题,但您可以考虑以下事项:

  • 制作构造函数internal。这将允许声明程序集中的任何类型调用构造函数,但在程序集之外没有任何内容。这意味着您在该程序集中编写的任何代码都负责调用工厂,这也意味着您不能在另一个程序集中声明该类的子类型,因为它将无法调用构造函数。
  • 一种类似的方法是使您公开的类抽象(或接口),然后声明实现抽象类或接口的类型internal(甚至private作为工厂的子类,因为它永远不会在工厂之外被引用) .
  • 需要一个只有工厂才能在构造函数中提供的令牌。这就是DataTable课堂的运作方式。虽然仍然可以调用构造函数,但用户必须传入null该值,并且至少很明显他们不应该这样做。
于 2013-10-07T16:13:48.137 回答
3

关键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; 
   } 
 }
}
于 2013-10-07T16:17:43.540 回答