コンフィギュレーション(Coc)よりも規則に基づいた単純なオブジェクトファクトリ実装


Baiduは
コンフィギュレーションよりも規則が優れている
コンフィギュレーションよりも約束が優れているのは簡単な概念です.システム、クラスライブラリ、フレームワークは、不要な構成を要求するのではなく、合理的なデフォルト値を仮定する必要があります.Ruby on RailsやEJB 3のようなポピュラーなフレームワークは、元のEJB 2.1仕様のようなフレームワークの構成の複雑さに反応するために、これらの原則を堅持し始めた.EJB 3の永続化のように、構成よりも優れた約束の例は、特別なBeanの永続化であり、このクラスを@Entityとしてマークする必要があります.フレームワークでは、テーブル名とカラム名がクラス名と属性名に基づいていると仮定します.システムにはフックも用意されており、必要に応じて名前を書き換えることができますが、ほとんどの場合、フレームワークで提供されているデフォルト値を使用すると、プロジェクトの実行が速くなることがわかります.
 
午前の合間に,Coc戦略に基づく単純な対象工場を開発した.目的はCocの基本的な実現ロジックを検証することである.
Cocは、値タイプ注入のため、XMLの代わりに依存関係を説明することはできませんが、DIの実装、構成、メンテナンスを比較的簡単にする良い方法です.
インタフェースと注入することはできませんが、DIの実装、構成、メンテナンスを大幅に簡素化するために良い改善を提供し、実際にはCocとXMLを宣言する方法を提供する必要があります.
組み合わせて使う.以下は私が書いた簡単な実現ですが、後期は絶えず改善され、豊かになります.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace DotNetConsole
{
	public delegate void InitObjectRelationShip (object thisObj);
	public class ObjectFactory
	{
		private static Random NextObj = null;

		public static object Create (Type ObjectType, InitObjectRelationShip InitMethod)
		{
			object CachedObject = CreateObject (ObjectType, InitMethod);
			if (NextObj == null)
				NextObj = new Random ();
			if (ObjectPoolService.GetCahce ().ContainsKey (ObjectType.ToString ())) {
				ObjectPoolService.SetCurrentPoolInUse (true);
				if (ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Count < ObjectPoolService.GetMaxSize ()) {
					ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Add (CachedObject);
				}
				
				int index = (int)NextObj.Next (ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Count);
				return ObjectPoolService.GetCahce ()[ObjectType.ToString ()][index];
				
			} else {
				
				if (ObjectPoolService.GetMaxSize () > ZERO_VALUE) {
					ObjectPoolService.SetCurrentPoolInUse (true);
					ObjectPoolService.GetCahce ().Add (ObjectType.ToString (), new List<object> ());
					ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Add (CachedObject);
				}
				
			}
			ObjectPoolService.SetCurrentPoolInUse (false);
			return CachedObject;
			
		}
		///in the future ,will implement proxy object not real object and 
		///base on proxy way, for object's method calling will be done as parall way.
		private static object CreateObject (Type ObjectType, InitObjectRelationShip InitMethodDef)
		{
			object FirstHeadObject = Activator.CreateInstance (ObjectType);
			if (InitMethodDef == null) {
				Type[] interfaceTypes = ObjectType.GetInterfaces ();
				if (interfaceTypes.Length != 0) {
					foreach (Type interfaceSubType in interfaceTypes) {
						if (interfaceSubType.Equals (typeof(IUserModeObjectInitor))) {
							((IUserModeObjectInitor)FirstHeadObject).Init ();
						}
					}
					
				}
				PropertyInfo[] proInfos = ObjectType.GetProperties ();
				if (proInfos.Length != 0) {
					foreach (PropertyInfo pro in proInfos) {
						if (pro.GetValue (FirstHeadObject, null) == null) {
							SetDepthObjectRelationShip (FirstHeadObject, pro);
						}
					}
				}
			} else {
				
				InitMethodDef (FirstHeadObject);
			}
			return FirstHeadObject;
		}
		private static void SetDepthObjectRelationShip (object MainObject, PropertyInfo PropertyType)
		{
			
			object PropertyObject = Activator.CreateInstance (PropertyType.PropertyType);
			PropertyType.GetSetMethod ().Invoke (MainObject, new object[] { PropertyObject });
			PropertyInfo[] innerProps = PropertyType.PropertyType.GetProperties ();
			if (innerProps.Length != 0) {
				foreach (PropertyInfo innerProerty in innerProps) {
					SetDepthObjectRelationShip (PropertyObject, innerProerty);
				}
			}
			
		}
		private const int ZERO_VALUE = 0;
	}
}


ObjectFactoryでは、オブジェクトの再利用率を低減し、メモリ使用量を低減し、クライアント・プログラムが同じタイプの複数のオブジェクトのどちらがサービスを提供するかに関心を持たないため、ステータスのないオブジェクトに基づくObjectPoolServiceも使用されています.また、MaxSize=0の場合、ObjectPoolServiceを使用することなく直接Create Objectすることができる.MaxSizeが大きいほど、Pool内のオブジェクトの再利用機会が小さくなり、メモリ使用率も高いため、MaxSizeはメモリ使用率と再利用率の構成を微調整するために使用できます.
Createメソッドには
InitObjectRelationShip

の依頼パラメータは、呼び出し者が指定する対象関係で組み立てる方式(Cocを使いたくない場合やXML構成とCocを組み合わせる場合は、以下のテストコードを見ることができる)で、各種DIポリシーを組み合わせる方が柔軟である.
 
またIUserModeObjectInitorというインタフェースも設計されており、組立プロセスをスキップしたり、開発者自身がオブジェクト関係を組み立てたりするのに使われていますが、侵入性が強く、
ObjectFactoryのCreateメソッドの依頼パラメータを使用することをお勧めします.ここではこのインタフェースを保持する目的は、柔軟な方法ですが、メソッドの依頼パラメータの処理を優先します.
using System;
namespace DotNetConsole
{
	public interface IUserModeObjectInitor
	{
		void Init();
	}
}

性能を向上させるために、極めて簡単なCacheも設計されています.
using System;
using System.Collections.Generic;
namespace DotNetConsole
{
	//use cassanadra db repleace in the future.
	public class ObjectPoolService
	{
		private static volatile Dictionary<string,List<object>> m_ObjectCache=null;
		private static int m_MaxSize=0;
		private static bool m_IsInUse=false;
		public static Dictionary<string, List<object>> GetCahce ()
		{
			if (m_ObjectCache == null)
				m_ObjectCache = new Dictionary<string, List<object>> ();
			return m_ObjectCache;
		}
		public static void SetMaxSize (int Size)
		{
			m_MaxSize = Size;
		}
		public static int GetMaxSize ()
		{
			return m_MaxSize;
		}
		public static void SetCurrentPoolInUse (bool isInUse)
		{
			m_IsInUse = isInUse;
		}
		public static bool GetCurrentPoolUsingState ()
		{
			return m_IsInUse;
		}
		public static void ShutdownPool ()
		{
			if (!m_IsInUse)
			{
				m_ObjectCache.Clear ();
			}
		}
		
		
	}
}


 
テストのコード:
using System;
using System.Reflection;
namespace DotNetConsole
{
	class MainClass
	{
		//statefulless Object gen! can reduce mem.
		public static void Main (string[] args)
		{
			ObjectPoolService.SetMaxSize (100);
			double timestart = DateTime.Now.Millisecond;
			((OrderService)ObjectFactory.Create (typeof(OrderService), x =>
					((OrderService)x).DAOObject = (OrderDAO)ObjectFactory.Create (typeof(OrderDAO), null))).ShowInfo ();
			for (int i = 0; i < 1000; i++)
			{
				((OrderService)ObjectFactory.Create (typeof(OrderService), null)).ShowInfo ();
			
			}
			ObjectPoolService.SetCurrentPoolInUse (false);
			ObjectPoolService.ShutdownPool ();
			double timeend= DateTime.Now.Millisecond;
			Console.WriteLine (timeend-timestart);
			Console.ReadLine();
		
		}
		
		
	}
}

 
以上,XMLでクラス間の依存関係を定義することをまず排除し,現在はCocポリシーに基づく基本オブジェクトファクトリのみを一時的に開発し,実現方式は簡単で,反射を利用してターゲットタイプの属性リストを取得し,その後属性のタイプ(一時的には参照タイプのみ)を取得することである.次に、対応するプロパティタイプのオブジェクトを反射でインスタンス化し、ターゲットオブジェクトに注入します.その後、依存するすべてのオブジェクトが初期化され、組み立てられます.
もちろんこれは最も基本的な実現です.これに基づいて開拓を考えるのは、比較的良い方法であり、徐々に進化したほうがいい.あとは仕事がたくさんあるので、
この単純なファクトリを扱うには、これを基に使用可能レベルの分散オブジェクトCache、分散階層型のObjectコンテナ、エージェントベースのオブジェクト作成、AOPを開発しなければならない.Emitを用いてエージェントベースのクラス作成を実現するため、その後、この「仮想」のタイプをこのObjectFactoryに渡してオブジェクトを生成すると、前のAOPやメソッドを呼び出したときにターゲットの「有能な」リアルオブジェクト(遅延ロード)をインスタンス化するなど、「仮想」のタイプ(エージェント)にやりたいことを挿入する可能性があります.またエージェントクラスをEmitでWCFのサービスタイプ(サービス契約の挿入などAttributeなど)に偽装することで,オブジェクトサービスの配信(サービスとしてネットワークに公開)機能を実現することができ,これらの強化は,いずれも現在のObjectFactoryを最下層の基盤として徐々に加えていく.後続の改良コードが続々と登録されます