www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.database design suggestion

reply bls <bizprac orange.fr> writes:
-- Sorry for posting on D.announce --

Hi, what do you people think about using the GoF
Factory (design) pattern ?
F.I.

abstract class Database {

     //common database stuff
     public abstract void connect(string user, string pw);
     // execSql(); prepare() etc...
}

abstract class DatabaseFactory {

    public abstract Database GetDatabase();
}

class PostgreSQL:Database {

     // common
    public override void connect(string user, string pw) {

    }
    //PostgreSQL specific
    public void funkyPGstuff() {}
}

class PostreSQLFactory:DatabaseFactory {

    public override Database GetDatabase() {

       return new PostgreSQL();

    }
}

class MySQL:Database {

     // common
    public override void connect(string user, string pw) {

    }
    //MySQL specific
    public void funkyMySQLstuff() {}
}

class MySQLFactory:DatabaseFactory {

    public override Database GetDatabase() {

       return new MySQL();

    }
}
Oct 10 2011
next sibling parent reply bls <bizprac orange.fr> writes:
well, the previous code was half baked, this should explain what I want 
to archive...
int main(string[] args)
{
	DatabaseFactory factory;
	
	if(args[0] == "MySQL")
		factory = new MySQLFactory();
	else
		factory = new PostreSQLFactory();

	updatePricelist(factory);
	return 0;
}

abstract class Database {

	//common database stuff
	public abstract void connect(string user, string pw);
	// execSql(); prepare() etc...
}

abstract class DatabaseFactory {

    public abstract Database GetDatabase();
}

final class PostgreSQL:Database {

	// common
    public override void connect(string user, string pw) {

    }
    //PostgreSQL specif
    public void funkyPGstuff() {}
}

final class PostreSQLFactory:DatabaseFactory {

    public override Database GetDatabase() {

       return new PostgreSQL();

    }
}

final class MySQL:Database {

	// common
    public override void connect(string user, string pw) {

    }
    //MySQL specif
    public void funkyMySQLstuff() {}
}

final class MySQLFactory:DatabaseFactory {

    public override Database GetDatabase() {

       return new MySQL();

    }
}
// Update PriceList without knowing the concrete database
void updatePricelist(DatabaseFactory factory) {
	Database db = factory.GetDatabase();
	//db.execSQL("UPDATE ...");
}
Oct 10 2011
parent reply Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 10/10/2011 7:19 AM, bls wrote:
 if(args[0] == "MySQL")
 factory = new MySQLFactory();
 else
 factory = new PostreSQLFactory();

Perhaps my design pattern knowledge is a bit shaky (it is), but isn't the point of a factory to give it hints about what you want to create, and it decides how to do it? Something like: Database d = Factory.gimmeAConnection("MySql", "server", "username", "pwd");
Oct 10 2011
parent bls <bizprac orange.fr> writes:
Am 11.10.2011 05:14, schrieb Johann MacDonagh:
 Perhaps my design pattern knowledge is a bit shaky (it is), but isn't
 the point of a factory to give it hints about what you want to create,
 and it decides how to do it? Something like:

 Database d = Factory.gimmeAConnection("MySql", "server", "username",
 "pwd");

I guess you describe the "Factory method" pattern. def : Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. My snippet is based on the "Abstract Factory" pattern. Also called "Factory design" pattern or simply "Factory" pattern . Indeed a bit confusing. def : Provide an interface for creating families of related or dependent objects without specifying their concrete classes. see also > http://www.dofactory.com/Patterns/Patterns.aspx
Oct 11 2011
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
bls Wrote:

 abstract class DatabaseFactory {
 
     public abstract Database GetDatabase();
 }

the method is usually called CreateInstance.
Oct 11 2011
parent bls <bizprac orange.fr> writes:
Am 11.10.2011 13:37, schrieb Kagamin:
 bls Wrote:

 abstract class DatabaseFactory {

      public abstract Database GetDatabase();
 }

the method is usually called CreateInstance.

I think this is true for the Factory _method_ pattern. I am using the _Abstract_ Factory pattern. See http://en.wikipedia.org/wiki/Abstract_factory_pattern Though createDatabaseInstance () seems to be reasonable/ (follows common coding conventions) -- slightly modified snippet-- import std.stdio; int main(string[] args) { IDatabaseFactory factory; if(args[0] == "MySQL") factory = new MySQLFactory(); else factory = new PostreSQLFactory(); updatePricelist(factory); return 0; } public interface IDatabase { //common database stuff alias open connect; public void open(const string[string] params); //alias close disconnect; //public void close(); // exec(); prepare() etc... } public interface IDatabaseFactory { public IDatabase createDatabaseInstance(); } final class PostgreSQL : IDatabase { // common public void open(const string[string] params) { } //PostgreSQL specific public void funkyPGstuff() {} } final class PostreSQLFactory : IDatabaseFactory { public IDatabase createDatabaseInstance() { return new PostgreSQL(); } } final class MySQL : IDatabase { // common public void open(const string[string] params) { } //MySQL specific public void funkyMySQLstuff() {} } final class MySQLFactory : IDatabaseFactory { public IDatabase createDatabaseInstance() { return new MySQL(); } } // Update PriceList without knowing the db backend void updatePricelist(IDatabaseFactory factory) { IDatabase db = factory.createDatabaseInstance(); db.connect([ "host" : "localhost", "database" : "test", "user" : "bls", "password" : "secret" ]); //db.exec("UPDATE ..."); }
Oct 11 2011
prev sibling parent Daniel Gibson <metalcaedes gmail.com> writes:
Am 10.10.2011 12:04, schrieb bls:
 -- Sorry for posting on D.announce --

 Hi, what do you people think about using the GoF
 Factory (design) pattern ?
 F.I.

 abstract class Database {

 //common database stuff
 public abstract void connect(string user, string pw);
 // execSql(); prepare() etc...
 }

 abstract class DatabaseFactory {

 public abstract Database GetDatabase();
 }

 class PostgreSQL:Database {

 // common
 public override void connect(string user, string pw) {

 }
 //PostgreSQL specific
 public void funkyPGstuff() {}
 }

 class PostreSQLFactory:DatabaseFactory {

 public override Database GetDatabase() {

 return new PostgreSQL();

 }
 }

 class MySQL:Database {

 // common
 public override void connect(string user, string pw) {

 }
 //MySQL specific
 public void funkyMySQLstuff() {}
 }

 class MySQLFactory:DatabaseFactory {

 public override Database GetDatabase() {

 return new MySQL();

 }
 }

I think this would make sense and JDBC does something similar, if I recall correctly. Cheers, - Daniel
Oct 11 2011