Home | FAQ | Contact me

Abstract class—a better illustration

This is how to implement abstraction for the purpose of folding common code into an abstract class that nevertheless needs to work with different data depending on the extending classes.

Our example is DAO code using MongoDB.

BaseDao.java:

Here we'll implement methods create() and readByOid(). They will need to use different MongoDB collections (and Morphia datastores). Also, there are other peculiarities needed like the .class of the caller.

import com.etretatlogiciels.mongo.MongoCollection;

public abstract class BaseDao< T >
{
    protected abstract MongoCollection getMongoCollection();
    protected abstract Class< T >      getClazz();

    public T create( T entity )
    {
        getMongoCollection().getMorphiastore().save( entity );
        return entity;
    }

    public T readByOid( ObjectId entityoid )
    {
        Query< T > query = getMongoCollection().getMorphiastore().createQuery( getClazz() );

        query.field( "_id" ).equal( entityoid );
        return query.get();
    }
}

In the two classes below, AccountDao and AddressDao, what's peculiar to the class is implemented (forcibly) for BaseDao to call. Any methods that are different and cannot be in common between AccountDao and AddressDao are implemented in their respective classes (and not in BaseDao).

AccountDao.java:
import com.etretatlogiciels.mongo.MongoCollection;

public class AccountDao extends BaseDao< Account >
{
    private static MongoCollection mongo = new MongoCollection( "accountdb", "accounts" );

    public AccountDao() { }

    private MongoCollection  getMongoCollection() { return mongo; }
    private Class< Account > getClazz() { return Account.class; }

    /* AccountDao-only implementation */
    ...
}
AddressDao.java:
import com.etretatlogiciels.mongo.MongoCollection;

public class AddressDao extends BaseDao< Address >
{
    private static MongoCollection mongo = new MongoCollection( "addressdb", "addresses" );

    public AddressDao() { }

    private MongoCollection  getMongoCollection() { return mongo; }
    private Class< Address > getClazz() { return Address.class; }

    /* AddressDao-only implementation */
    ...
}

We won't flesh this out, just enough to show the distinction between two or more sets of data. And we won't show super class MongoDB.

MongoCollection.java:
package com.etretatlogiciels.mongo;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.mongodb.DBCollection;

public class MongoCollection extends MongoDB
{
    private String       collectionname;
    private DBCollection collection;

    public MongoCollection( String databasename, String collectionname )
    {
        super( databasename );
        this.collectionname = collectionname;
        this.collection     = this.database.getCollection( collectionname );
    }

    public String getCollectionname() { return this.collectionname; }

    public DBCollection getCollection()
    {
        return this.collection;
    }

    private Morphia   morphia      = null;
    private Datastore morphiastore = null;

    /**
     * If Morphia use is desired, get its Datastore for this database.
     * @return Morphia datastore.
     */
    public Datastore getMorphiastore()
    {
        if( this.morphiastore == null )
        {
            this.morphia      = new Morphia();
            this.morphiastore = morphia.createDatastore( getMongodb(), getDatabasename() );
        }

        return this.morphiastore;
    }
}