简单工厂模式Simple Factory根据提供给它的数据,返回一个类的实例。通常它返回的类都有一个公共的父类(或者接口对象)。
简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类。简单工厂实例化的类具有相同的接口或者基类,在子类比较固定并不需要扩展时,可以使用简单工厂。如数据库生产工厂就是简单工厂的一个应用。
采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性;缺点是可实例化的类型在编译期间已经被确定,如果增加新类 型,则需要修改工厂,不符合OCP(开闭原则)的原则。简单工厂需要知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用。
下面是我实例中的类结构图,它有一个ICreate的公共接口,有一个方法叫Create,返回值为Void
其中公用的接口代码如下:(最后工厂的返回值类型)
1 /// <summary> 2 /// 简单工厂接口,返回值类型 3 /// </summary> 4 public interface ICreate 5 { 6 void Create(); 7 }
而下面,分别用people和animal两个类去实现了ICreate接口,并实现了它的Create方法。
1 /// <summary> 2 /// 人类实现工厂接口 3 /// </summary> 4 public class People : ICreate 5 { 6 7 #region ICreate 成员 8 9 public void Create() 10 { 11 Console.WriteLine("创建人类"); 12 } 13 14 #endregion 15 } 16 /// <summary> 17 /// 动物实现工厂接口 18 /// </summary> 19 public class Animal : ICreate 20 { 21 22 #region ICreate 成员 23 24 public void Create() 25 { 26 Console.WriteLine("创建动物"); 27 } 28 29 #endregion 30 }
而对于外界来说,会有另一个类去为外界提供服务,它们可以需要建立People或者Animal类型的实现,代码如下:
1 public class CreateFactory 2 { 3 public static ICreate GeneratorCreate(string createName) { 4 switch (createName) 5 { 6 case "People": 7 return new People(); 8 case "Animal": 9 return new Animal(); 10 default: 11 throw new NotImplementedException(); 12 } 13 }
最后,在使用它时,直接使用CreateFactory.GeneratorCreate("类型条件名")即可生成你的类对象了。
单件模式(Singleton)要求一个类有且仅有一个实例,并且提供了一个全局的访问点。
从概念上来研究一下它的实现,不考虑纯种安全
1 public sealed class Singlton 2 { 3 static Singlton instance = null; 4 private Singlton() { } 6 7 public static Singlton Instance 8 { 9 get 10 { 11 if (instance == null) 12 { 13 return new Singlton(); 14 } 15 return instance; 16 } 17 } 18 }
上面的实现方式,对于多线程会有问题,因为Singlton 对象可能不指一次被创建,而罪魁祸首就是if (instance == null)这句话,它并不是线程安全的。
如果希望实现线程安全的单件,我们最先想到的应该就是借助lock机制来实现,代码可能是这样:
1 public sealed class Singlton 2 { 3 static Singlton instance = null; 4 5 static readonly object o = new object(); 6 7 Singlton() 8 { } 9 10 public static Singlton Instance 11 { 12 get 13 { 14 lock (o) 15 { 16 if (instance == null) 17 { 18 return new Singlton(); 19 } 20 return instance; 21 } 22 } 23 } 24 }
而我们使用静态对象在静态结构方法里为它进行初始化,这种方式也非常在程序中看到,如:
1 public sealed class Singlton 2 { 3 static readonly Singlton instance = null; 4 5 static Singlton() 6 { instance = new Singlton();} 7 8 public static Singlton Instance 9 { 10 get 11 { 12 return instance; 13 } 14 } 15 }
这种方法及其它单件模式有一个问题,就是如果希望去更新单件对象的值,是无法实现的,比如,instance对象希望从数据库中取出一个列表,而列表的信息有可能
发生变化,怎样保证instance里取的是最新的信息呢,这样我们可以在单件中引入时间触发器的概念,代码如下:
1 public class CategoryRepository : Car_RentalRepositoryBase, ICategoryRepository 2 { 3 #region 静态树结构,每1分钟去获一下数据库 4 static List<Category> categoryList = null; 5 /// <summary> 6 /// 数据实体 7 /// </summary> 8 public static volatile List<Category> Instance = null; 9 static CategoryRepository categoryRepository = new CategoryRepository(); 10 static System.Timers.Timer sysTimer = new System.Timers.Timer(600000); 11 static CategoryRepository() 12 { 13 Reload();//第一次加载 14 sysTimer.AutoReset = true; 15 sysTimer.Enabled = true; 16 sysTimer.Elapsed += new System.Timers.ElapsedEventHandler(sysTimer_Elapsed); 17 sysTimer.Start(); 18 } 19 20 /// <summary> 21 /// 被订阅了Elapsed事件的方法,每隔一段时间去重新获取数据列表 22 /// </summary> 23 /// <param name="sender"></param> 24 /// <param name="e"></param> 25 static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 26 { 27 Reload(); 28 } 29 30 internal static void Reload() 31 { 32 categoryList = categoryRepository.GetModel().OrderBy(i => i.SortNumber).ToList(); 33 Instance = categoryList.Where(i => i.ID != 1).ToList(); 34 } 35 }
这种方式解决了实例不能获取最新的问题。
最后,奉献出国外牛人写了的泛型单件类,如果实现的类直接继承它即可。
1 /// <summary> 2 /// 泛型单例基类 3 /// </summary> 4 public abstract class Singleton<TEntity> where TEntity : class 5 { 6 private static readonly Lazy<TEntity> _instance 7 = new Lazy<TEntity>(() => 8 { 9 var ctors = typeof(TEntity).GetConstructors( 10 BindingFlags.Instance 11 | BindingFlags.NonPublic 12 | BindingFlags.Public); 13 if (ctors.Count() != 1) 14 throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.", typeof(TEntity))); 15 var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate); 16 if (ctor == null) 17 throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.", typeof(TEntity))); 18 return (TEntity)ctor.Invoke(null); 19 }); 20 21 public static TEntity Instance 22 { 23 get { return _instance.Value; } 24 } 25 }
感谢您好阅读,希望本文章对您有帮助。
相关链接:基础才是重中之重~延迟初始化
参考 文献:
http://technet.microsoft.com/zh-cn/magazine/dd997286%28VS.95%29.aspx
http://www.fascinatedwithsoftware.com/blog/post/2011/07/13/A-Generic-Singleton-Class.aspx