Subclassing Singleton 
Author Message
 Subclassing Singleton

How would I go about creating a Singleton class that can be subclassed?
Specifically, I want to avoid the GoF solution of a private registry of
subclasses, simply because I don't want to have to edit the base class
every time I create a subclass. The registry-based solution maintains
a hash of all known subclasses. To me, this breaks the encapsulation
of the solution.

Is there a way to do this via reflection/introspection:

public class BaseSingleton
{
  ...
  protected Instance()
  {
    // return unique instance of subclass
    ???
  }

Quote:
}

public class MySingleton : BaseSingleton
{
  ???
Quote:
}



Sun, 17 Apr 2005 23:30:04 GMT  
 Subclassing Singleton
    Here's a conceptual workup of using a BaseSingleton.  However,
you'll have to note the limitations on your code with this.  Depending
on what you need, it may suffice.

//**************************
public abstract class BaseSingleton
{
    protected static BaseSingleton instance;
    protected BaseSingleton()
    {
    }
    public static BaseSingleton Instance
    {
        get { return instance; }
    }

Quote:
}

//**************************
public class FooSingleton : BaseSingleton
{
    static FooSingleton()
    {
        instance = new FooSingleton();
    }
    protected FooSingleton()
    {
    }
    public static FooSingleton DefinedInstance
    {
        get { return instance; }
    }

Quote:
}

//**************************
public class BarSingleton : BaseSingleton
{
    static BarSingleton()
    {
        instance = new BarSingleton();
    }
    protected BarSingleton()
    {
    }
    public static BarSingleton DefinedInstance
    {
        get { return instance; }
    }
Quote:
}

//**************************

Chris R.



Quote:
> Great! Thanks. I guess what I was trying to accomplish was to
"pull-up"
> the instance member, Instance property, and 'get' logic into the base
class.

> I'm still curious if this is possible ;)

> - Mark



Mon, 18 Apr 2005 02:45:03 GMT  
 Subclassing Singleton
    The more I thought about this, the more I believe you need to split
the Data out of your class and create a class of static fields and
methods, rather than putting that in your base class.
    This seems to be a more logical design from what I can perceive of
what you're trying to accomplish.

public class DataObject
{
    protected static SqlConnection sqlConnector;
    protected static DAOSet dataSet1;
    static DataObject()
    {
        //sqlConnector = //code
        //dataSet1 = //code
    }
    public static SqlConnection SqlConnector
    {
        get {return sqlConnector; }
    }
    public static DAOSet DataSet1
    {
        get {return dataSet1; }
    }

Quote:
}

Chris R.



Quote:
> Great! Thanks. I guess what I was trying to accomplish was to
"pull-up"
> the instance member, Instance property, and 'get' logic into the base
class.

> I'm still curious if this is possible ;)

> - Mark



Mon, 18 Apr 2005 03:35:52 GMT  
 Subclassing Singleton
Ouch, I knew that and I still made the same mistake...
    "static members are not inherited"

But heck, once I saw what Mark was trying to do, I could see a realistic
solution that wasn't so mentally convoluted.  Keep things simple (if
possible).

Chris R.


Quote:

> > Here is my solution -- I invite all to improve upon it.

> <snip>

> As soon as you've got another class, you're going to run into
problems -
> they'll both try to register the same instance, so you'll only
actually
> be able to get one of them. I thought the idea was that you could have
> one of *each* of the subclass instances, not one in total? Currently
if
> you have Supplier in the same way as Customer, then one of
> Customer.Instance or Supplier.Instance will throw a
ClassCastException,
> depending on which was constructed first. It strikes me you haven't
> really defined what BaseSingleton.Instance should actually return, in
the
> case where you've got more than one subclass.

> I would also personally make everything private and have protected
> properties to access the resources.

> --
> Jon Skeet

> If replying to the group, please do not mail me at the same time



Mon, 18 Apr 2005 05:32:07 GMT  
 Subclassing Singleton
Hrm. What you might do is have a base class that has only
a protected constructor which provides all these commonalities.

Then, each subclass will provide it's own singleton stuff
(Instance property, etc).

For example:

public DAOSingletonBase
{
  protected DAOSingletonBase() {}

  protected SqlConnection GetSqlConnection()...

  /* yadda, yadda, yadda */

Quote:
}

public MySingleton
{
   private static MySingleton instance;

   protected MySingleton() : base() {}

   public MySingleton Instance
   {
     get
     {
        if( instance == null )
          MySingleton.instance = new MySingleton();

        return MySingleton.instance;
     }
   }

   /* yadda, yadda, yadda */

Quote:
}

That might work better for you.

-c



Quote:
> My requirements are self-imposed :) Here is my idea:

> I have a client-server app in which I have a data
> access object for each class of business object. Each of these
> DAO's has the same SQL connection logic, protected DataSet member,
> etc. There is no need for more than one instance of each of these
> on the client. Hence, the Singleton requirement.

> The idea was to limit the instances to one by using a Singleton,
> and to refactor the redundant logic out of the DAO's by
> pulling it up to a base class.

> My thought was that this base class should be a Singleton, and
> subclasses of it would be responsible for business object specific
> logic, i.e. SQL queries. Each subclass would then inherit the
> connection logic, protected DataSet member, etc. from the base
> class, and still be limited to a single instance each.

> Maybe this clears it up ;)

> Thanks again,
> Mark


> > How would I go about creating a Singleton class that can be
subclassed?
> > Specifically, I want to avoid the GoF solution of a private registry
of
> > subclasses, simply because I don't want to have to edit the base
class
> > every time I create a subclass. The registry-based solution
maintains
> > a hash of all known subclasses. To me, this breaks the encapsulation
> > of the solution.

> > Is there a way to do this via reflection/introspection:

> > public class BaseSingleton
> > {
> >   ...
> >   protected Instance()
> >   {
> >     // return unique instance of subclass
> >     ???
> >   }
> > }

> > public class MySingleton : BaseSingleton
> > {
> >   ???
> > }



Mon, 18 Apr 2005 01:39:34 GMT  
 Subclassing Singleton
Here is my solution -- I invite all to improve upon it.

Thanks,
Mark

using System;
using System.Data;
using System.Data.SqlClient;

namespace Test
{
  public abstract class BaseSingleton
  {
        protected static BaseSingleton instance;
        protected static readonly string credentials = "server=localhost;Initial Catalog=Northwind;uid=sa;pwd=";
        protected SqlConnection con = new SqlConnection(credentials);
        protected SqlDataAdapter da = new SqlDataAdapter();
        protected DataSet ds = new DataSet();

        protected BaseSingleton(){}

        protected static BaseSingleton Instance
        {
          get { return instance; }
        }
  }

  public class Customer : BaseSingleton
  {
        SqlCommand cmdSelect = null;

        static Customer()
        {
          instance = new Customer();
        }

        protected Customer()
        {
          cmdSelect = new SqlCommand("SELECT CustomerID, CompanyName FROM Customers", con);
          cmdSelect.CommandTimeout = 30;
          da.SelectCommand = cmdSelect;
        }

        public static new Customer Instance
        {
          get { return (Customer)instance; }
        }

        public DataSet GetCustomers()
        {
          con.Open();
          da.Fill(ds, "Customers");
          con.Close();
          return ds;
        }
  }

  public class Test {
        public static void Main() {
          Customer c = Customer.Instance;
          DataSet ds = c.GetCustomers();
        }
  }

Quote:
}



Mon, 18 Apr 2005 03:51:32 GMT  
 Subclassing Singleton
Boy, it's so simple once you have the answer!

One last question: When does "static Customer() {...}" get called? When the
application is instantiated? When the class that references it is
instantiated? Or when Customer.Instance() is called?

I guess that was four questions...but I hope you catch my drift.

Thanks,
Mark


Quote:
>     I have to ask, why not just use a has-a instead of an is-a solution
> for this?  Now, your Customer can have all fields and methods static.

> //***********************
> public class DataContainer
> {
>     protected static readonly string credentials =
> "server=localhost;Initial Catalog=Northwind;uid=sa;pwd=";
>     protected SqlConnection con = new SqlConnection(credentials);
>     protected SqlDataAdapter da = new SqlDataAdapter();
>     protected DataSet ds = new DataSet();

>     public SqlDataAdapter DA
>     {
>         get
>         {
>             return da;
>         }
>     }
>     public DataSet DS
>     {
>         get
>         {
>             return ds;
>         }
>     }
>     public SqlConnection Con
>     {
>         get
>         {
>             return con;
>         }
>     }
> }

> //***********************
> public class Customer
> {
>     static DataContainer dataCon;
>     static SqlCommand cmdSelect = null;

>     static Customer()
>     {
>         dataCon = new DataContainer();
>         cmdSelect = new SqlCommand("SELECT CustomerID, CompanyName FROM
> Customers", dataCon.Con);
>         cmdSelect.CommandTimeout = 30;
>         dataCon.DA.SelectCommand = cmdSelect;
>     }

>     public static DataSet GetCustomers()
>     {
>         dataCon.Con.Open();
>         dataCon.DA.Fill(dataCon.DS, "Customers");
>         dataCon.Con.Close();
>         return dataCon.DS;
>     }
>  }

> //***********************
> public class Test
> {
>     public static void Main()
>     {
>         DataSet ds = Customer.GetCustomers();
>     }
> }



> > Here is my solution -- I invite all to improve upon it.

> > Thanks,
> > Mark

> > using System;
> > using System.Data;
> > using System.Data.SqlClient;

> > namespace Test
> > {
> >   public abstract class BaseSingleton
> >   {
> > protected static BaseSingleton instance;
> > protected static readonly string credentials =
> "server=localhost;Initial Catalog=Northwind;uid=sa;pwd=";
> > protected SqlConnection con = new SqlConnection(credentials);
> > protected SqlDataAdapter da = new SqlDataAdapter();
> > protected DataSet ds = new DataSet();

> > protected BaseSingleton(){}

> > protected static BaseSingleton Instance
> > {
> >           get { return instance; }
> > }
> >   }

> >   public class Customer : BaseSingleton
> >   {
> > SqlCommand cmdSelect = null;

> > static Customer()
> > {
> >   instance = new Customer();
> > }

> > protected Customer()
> > {
> >   cmdSelect = new SqlCommand("SELECT CustomerID, CompanyName FROM
> Customers", con);
> >   cmdSelect.CommandTimeout = 30;
> >   da.SelectCommand = cmdSelect;
> > }

> > public static new Customer Instance
> > {
> >           get { return (Customer)instance; }
> >   }

> > public DataSet GetCustomers()
> > {
> >   con.Open();
> >   da.Fill(ds, "Customers");
> >   con.Close();
> >   return ds;
> > }
> >   }

> >   public class Test {
> > public static void Main() {
> >   Customer c = Customer.Instance;
> >   DataSet ds = c.GetCustomers();
> > }
> >   }

> > }



Mon, 18 Apr 2005 06:35:41 GMT  
 Subclassing Singleton
    I have to ask, why not just use a has-a instead of an is-a solution
for this?  Now, your Customer can have all fields and methods static.

//***********************
public class DataContainer
{
    protected static readonly string credentials =
"server=localhost;Initial Catalog=Northwind;uid=sa;pwd=";
    protected SqlConnection con = new SqlConnection(credentials);
    protected SqlDataAdapter da = new SqlDataAdapter();
    protected DataSet ds = new DataSet();

    public SqlDataAdapter DA
    {
        get
        {
            return da;
        }
    }
    public DataSet DS
    {
        get
        {
            return ds;
        }
    }
    public SqlConnection Con
    {
        get
        {
            return con;
        }
    }

Quote:
}

//***********************
public class Customer
{
    static DataContainer dataCon;
    static SqlCommand cmdSelect = null;

    static Customer()
    {
        dataCon = new DataContainer();
        cmdSelect = new SqlCommand("SELECT CustomerID, CompanyName FROM
Customers", dataCon.Con);
        cmdSelect.CommandTimeout = 30;
        dataCon.DA.SelectCommand = cmdSelect;
    }

    public static DataSet GetCustomers()
    {
        dataCon.Con.Open();
        dataCon.DA.Fill(dataCon.DS, "Customers");
        dataCon.Con.Close();
        return dataCon.DS;
    }
 }

//***********************
public class Test
{
    public static void Main()
    {
        DataSet ds = Customer.GetCustomers();
    }

Quote:
}



Quote:
> Here is my solution -- I invite all to improve upon it.

> Thanks,
> Mark

> using System;
> using System.Data;
> using System.Data.SqlClient;

> namespace Test
> {
>   public abstract class BaseSingleton
>   {
> protected static BaseSingleton instance;
> protected static readonly string credentials =

"server=localhost;Initial Catalog=Northwind;uid=sa;pwd=";
Quote:
> protected SqlConnection con = new SqlConnection(credentials);
> protected SqlDataAdapter da = new SqlDataAdapter();
> protected DataSet ds = new DataSet();

> protected BaseSingleton(){}

> protected static BaseSingleton Instance
> {
>           get { return instance; }
> }
>   }

>   public class Customer : BaseSingleton
>   {
> SqlCommand cmdSelect = null;

> static Customer()
> {
>   instance = new Customer();
> }

> protected Customer()
> {
>   cmdSelect = new SqlCommand("SELECT CustomerID, CompanyName FROM
Customers", con);
>   cmdSelect.CommandTimeout = 30;
>   da.SelectCommand = cmdSelect;
> }

> public static new Customer Instance
> {
>           get { return (Customer)instance; }
>   }

> public DataSet GetCustomers()
> {
>   con.Open();
>   da.Fill(ds, "Customers");
>   con.Close();
>   return ds;
> }
>   }

>   public class Test {
> public static void Main() {
>   Customer c = Customer.Instance;
>   DataSet ds = c.GetCustomers();
> }
>   }

> }



Mon, 18 Apr 2005 04:59:00 GMT  
 Subclassing Singleton

Quote:

> Here is my solution -- I invite all to improve upon it.

<snip>

As soon as you've got another class, you're going to run into problems -
they'll both try to register the same instance, so you'll only actually
be able to get one of them. I thought the idea was that you could have
one of *each* of the subclass instances, not one in total? Currently if
you have Supplier in the same way as Customer, then one of
Customer.Instance or Supplier.Instance will throw a ClassCastException,
depending on which was constructed first. It strikes me you haven't
really defined what BaseSingleton.Instance should actually return, in the
case where you've got more than one subclass.

I would also personally make everything private and have protected
properties to access the resources.

--
Jon Skeet

If replying to the group, please do not mail me at the same time



Mon, 18 Apr 2005 04:45:23 GMT  
 
 [ 24 post ]  Go to page: [1] [2]

 Relevant Pages 
 

 
Powered by phpBB® Forum Software