C# 为接受参数/参数的类创建单例工厂
首先,我是在一个网站上读到这篇文章的,它基本上告诉我,我根本不应该使用单例 最常见的情况是,在创建实例时,单例不允许指定任何参数——否则,对实例的第二个请求(但使用不同的参数)可能会有问题!(如果对于具有相同参数的所有请求都应访问相同的实例,则工厂模式更合适。) 因为我需要参数,同样的实例也需要相同的参数,所以我得出结论,我需要一个工厂模式 但是我在任何地方都找不到一个好的工厂模式实现 如果您发现任何好的带有参数的c#单例工厂模式实现,请告诉我 好的,我将尝试在这里非常具体。。。希望这能解释我的情况 最欢迎其他方法。我只是结合了很多实现——我的理解可能有偏差 所以我有一个类'a'。它是一个用于连接到数据库-数据库连接的类 连接需要4个参数&约束条件为:C# 为接受参数/参数的类创建单例工厂,c#,oop,parameters,singleton,factory,C#,Oop,Parameters,Singleton,Factory,首先,我是在一个网站上读到这篇文章的,它基本上告诉我,我根本不应该使用单例 最常见的情况是,在创建实例时,单例不允许指定任何参数——否则,对实例的第二个请求(但使用不同的参数)可能会有问题!(如果对于具有相同参数的所有请求都应访问相同的实例,则工厂模式更合适。) 因为我需要参数,同样的实例也需要相同的参数,所以我得出结论,我需要一个工厂模式 但是我在任何地方都找不到一个好的工厂模式实现 如果您发现任何好的带有参数的c#单例工厂模式实现,请告诉我 好的,我将尝试在这里非常具体。。。希望这能解释我的
<which access modifier ?> Class A {
private Class A(string hostname, string port, string username, string pw_hash) {
//create a new instance with the specified parameters
}
//other methods on the connection
protected void close() {
//close the connection
}
}
public class AFactory//should it inherit class A?? {
private IList<A> connections = new List<A>();
private AFactory()
{
//do something
}
private static readonly Lazy<AFactory> lazy
= new Lazy<AFactory>(() => new AFactory());
public static AFactory Instance { get { return lazy.Value; } }
public A getA(string hostname, string service, string username, string pw_hash)
{
foreach (A a in A)
{
if (a.hostname == hostname && a.service == service && a.username == username)
return a;
}
A d = new A(hostname, service, username, pw_hash);
connections.Add(d);
return d;
}
A类{
私有类A(字符串主机名、字符串端口、字符串用户名、字符串pw_散列){
//使用指定的参数创建新实例
}
//连接上的其他方法
受保护的无效关闭(){
//关闭连接
}
}
公共类AFactory//是否应该继承类A??{
私有IList连接=新列表();
私人工厂
{
//做点什么
}
私有静态只读惰性
=新懒惰(()=>新工厂());
公共静态工厂实例{get{return lazy.Value;}}
public A getA(字符串主机名、字符串服务、字符串用户名、字符串pw_散列)
{
foreach(A中的A)
{
if(a.hostname==hostname&&a.service==service&&a.username==username)
返回a;
}
A d=新的A(主机名、服务、用户名、pw_散列);
增加(d);
返回d;
}
现在,只要类A构造函数是公共的,它就可以很好地工作——但它有点违背了单例的目的。
我需要做什么才能让代码正常工作
对于指定的参数,我只需要一个类A实例。
谢谢
Indrajit试试这个:
此接口从工厂初始值设定项公开,并包含公开的方法和属性
public interface IDatabase
{
string ConnectionString { get; set; }
IDataReader ExecuteSql(string sql);
}
Factory基抽象类,在该类中可以对不同类型的数据库工厂执行通用功能
public abstract class FactoryBase
{
public FactoryBase() { }
public abstract IDatabase GetDataLayer();
}
包含调用的具体sql类。请查看ExecuteSql方法。该连接在命令中是自包含的,因此您不必担心打开、关闭和处理它
public class SQL : IDatabase
{
private string m_ConnectionString = string.Empty;
public string ConnectionString
{
get { return m_ConnectionString; }
set { m_ConnectionString = value; }
}
public IDataReader ExecuteSql(string sql)
{
using (var command = new SqlCommand(sql, new SqlConnection(ConnectionString)) { CommandType = CommandType.Text, CommandText = sql, CommandTimeout = 0 })
{
if (command.Connection.State != ConnectionState.Open) command.Connection.Open();
return command.ExecuteReader();
}
}
}
创建Sql具体类实例的Sql工厂类
class SQLFactory : FactoryBase
{
public override IDatabase GetDataLayer()
{
return new SQL();
}
}
开发人员用于传入工厂类型并返回IDatabase的工厂初始值设定项类
public static class FactoryInitializer
{
public static IDatabase LoadFactory<T>(string connectionstring) where T : FactoryBase, new()
{
var factory = new T();
var data = factory.GetDataLayer();
data.ConnectionString = connectionstring;
return data;
}
}
公共静态类FactoryInitializer
{
公共静态IDatabase LoadFactory(string connectionstring),其中T:FactoryBase,new()
{
var factory=newt();
var data=factory.GetDataLayer();
data.ConnectionString=连接字符串;
返回数据;
}
}
然后将其用作:
var factory = FactoryInitializer.LoadFactory<SQLFactory>(connectionString);
factory.ExecuteSql("SELECT ...");
var-factory=FactoryInitializer.LoadFactory(connectionString);
ExecuteSql(“选择…”);
然后,您可以创建一个OracleFactory和一个Oracle混凝土类,并以相同的方式使用它。所以我已经这样做了,它可以工作了……您能告诉我它是否正确。它是否线程安全
public Class A
{
private A(string hostname, string port, string username, string pw_hash) {
//create a new instance with the specified parameters
}
//other methods on the connection
protected void close() {
//close the connection
}
public class AFactory
{
private IList<A> connections = new List<A>();
private AFactory()
{
//do something
}
private static readonly Lazy<AFactory> lazy
= new Lazy<AFactory>(() => new AFactory());
public static AFactory Instance { get { return lazy.Value; } }
public A getA(string hostname, string service, string username, string pw_hash)
{
foreach (A a in connections)
{
if (a.hostname == hostname && a.service == service && a.username == username)
return a;
}
A d = new A(hostname, service, username, pw_hash);
connections.Add(d);
return d;
}
}
}
此实现是否存在明显错误?工厂用于生成对象而不是管理对象。我认为DB连接管理器更适合您的情况。您可以将管理器声明为单例。对于单个连接,您可以使用内部类/结构 请参见以下示例:
class DBConnectionManager
{
struct Connection
{
public string Hostname;
public string ServerName;
public string UserName;
public string Password;
public void Connect()
{
}
public void Close()
{
}
}
private static s_instance;
public static DBConnectionManager Instance
{
get {return s_instance; }
}
private List<Connection> m_connections;
public Connection GetConnection(string hostname, string serverName, string userName, string password)
{
// if already exist in m_connections
// return the connection
// otherwise create new connection and add to m_connections
}
public void CloseConnection(string hostname, string serverName, string userName, string password)
{
// if find it in m_connections
// then call Close()
}
public void CloseAll()
{
//
}
}
classdbconnectionmanager
{
结构连接
{
公共字符串主机名;
公共字符串ServerName;
公共字符串用户名;
公共字符串密码;
公共void Connect()
{
}
公众假期结束()
{
}
}
私有静态s_实例;
公共静态DBConnectionManager实例
{
获取{return s_instance;}
}
私有列表m_连接;
公共连接GetConnection(字符串主机名、字符串服务器名、字符串用户名、字符串密码)
{
//如果m_连接中已存在
//返回连接
//否则,创建新连接并添加到m_连接
}
public void CloseConnection(字符串主机名、字符串服务器名、字符串用户名、字符串密码)
{
//如果在m_连接中找到它
//然后调用Close()
}
公共空间关闭所有()
{
//
}
}
您可以尝试以下方法:
public static class Singlett<Param,T>
where T : class
{
static volatile Lazy<Func<Param, T>> _instance;
static object _lock = new object();
static Singlett()
{
}
public static Func<Param, T> Instance
{
get
{
if (_instance == null)
{
_instance = new Lazy<Func<Param, T>>(() =>
{
lock (Singlett<Param,T>._lock)
{
try
{
ConstructorInfo constructor = null;
Type[] methodArgs = { typeof(Param) };
constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, methodArgs, null);// Binding flags excludes public constructors.
if (constructor == null)
{
constructor = typeof(T).GetConstructor(BindingFlags.Public, null, methodArgs, null);
if (constructor == null)
return delegate(Param o) { return (T)Activator.CreateInstance(typeof(T), new object[] { o }); };
}
return delegate(Param o) { return (T)constructor.Invoke(new object[] { o }); };
}
catch (Exception exception)
{
throw exception;
}
}
});
}
return _instance.Value;
}
}
}
你可以写:
int i = 10;
MyClass class = Singlett<int,MyClass>.Instance(i);
inti=10;
MyClass=Singlett.Instance(i);
这个问题与Java无关。为什么您需要工厂来创建单例对象?只要a类构造函数是公共的
您就可以将a
作为工厂的内部类来实现
int i = 10;
MyClass class = new MyClass(i);
int i = 10;
MyClass class = Singlett<int,MyClass>.Instance(i);