0

I am creating a very basic Cache object. Here is my code:

Cache.java is an abstract class meant to be overriden.

public abstract class Cache {

    protected Date dateCreated;
    protected long expiration;
    private BuildStrategy strategy;

    protected Cache(long expiration, BuildStrategy strategy) {
        this.dateCreated = new Date();
        this.expiration = expiration;
        this.strategy = strategy;
        strategy.buildAndUpdate();
    }

    private final boolean isExpired() {
        long duration = new Date().getTime() - this.dateCreated.getTime();

        if (duration > expiration) {
            return true;
        }
        return false;
    }

    protected void build() {
        if (!isExpired())
            return;
        setDateCreated(new Date());
        buildAndUpdate();
    }

    protected abstract void buildAndUpdate();

    final Date getDateCreated() {
        return dateCreated;
    }

    final void setDateCreated(Date dateCreated) {
        this.dateCreated = dateCreated;
    }

    final long getExpiration() {
        return expiration;
    }

    final void setExpiration(long expiration) {
        this.expiration = expiration;
    }
}

This is a sample of a class that overrides it, ACache.java:

   public class ACache extends Cache {

    protected ACache(long expiration) {
        super(expiration);
    }

    private Object variableToBeUpdated;

    public Object getVariableToBeUpdated() {
        return variableToBeUpdated;
    }

    public void setVariableToBeUpdated(Object variableToBeUpdated) {
        this.variableToBeUpdated = variableToBeUpdated;
    }

    @Override
    protected void buildAndUpdate() {
        // ...connects to the database etc...
        // ...once database stuff is done, update variableToBeUpdated
        // NOTE: Other caches may implement buildAndUpdate() differently, that's
        // why it's abstract
    }
}

My problem here is that I want to hide the buildAndUpdate() method and just expose the build() method of Cache because in order for the Cache to be updated, I would want to check if it's expired first.

Since buildAndUpdate() is protected, the method can be accessed by the class itself. How do I proceed with what I want to do? How can you improve my implementation?

EDIT 1: Took ControlAltDel and Turing85's advice and went with IoC. I created an interface called BuildStrategy that has a void buildAndUpdate() method. Is this correct?

7
  • 2
    buildAndUpdate in the Cache class is abstract, so it cannot be called from ACache, if that's what you're worried about. Commented May 27, 2015 at 19:45
  • What? It totally can be called in ACache. ACache overrides the buildAndUpdate() method and since it's protected abstract in Cache, that means it would have the protected modifier when overriden in ACache That's the problem. Commented May 27, 2015 at 19:47
  • Who consumes/uses a cache? Only package level types or anyone? Commented May 27, 2015 at 19:49
  • I basically have another class that would manage all the caches. Yes, they're in the same package. ACache.java, Cache.java, CacheManager.java are all in the same package. Commented May 27, 2015 at 19:50
  • as a design tip, I would suggest you make your class generic Commented May 27, 2015 at 19:51

3 Answers 3

2

One way you could go would be to get rid of this method entirely, and instead create at BuildAndUpdate class, which would be a required parameter in the constructor. You could then subclass your Cache class, and in an empty constructor, initialize the superclass with a BuildAndUpdate object.

Make sense?

Sign up to request clarification or add additional context in comments.

5 Comments

Hmm... I got lost at ...which would be a required parameter in the constructor. I don't understand what you mean.
@MiguelPortugal look at my link. Basically, you need to construct an management-object, which manages the buildAndUpdate-process of one particular Cache and pass this management-object into the Cache class (which should store it as an attribute for future use).
@Turing85 @ControlAltDel Please check my latest edit. I created an interface called BuildStrategy that has a void buildAndUpdate() method. So for every Cache that has a different buildAndUpdate() method, I should make a class that implements BuildStrategy right?
@MiguelPortugal Yes you got the idea
1

you can use generics. Not sure why you need class to be abstract. People who require special behaviour, they can extend your class.

import java.util.Date;
import java.util.Map;

public  class  Cache<K,V> {
private Map<K,V> map;
protected Date dateCreated;
protected long expiration;

protected Cache(long expiration) {
    this.dateCreated = new Date();
    this.expiration = expiration;
    buildAndUpdate();
}

private final boolean isExpired(){
    long duration = new Date().getTime() - this.dateCreated.getTime();

    if (duration > expiration){
        return true;
    }
    return false;
}

protected void build(){
    if (!isExpired()) return;
    setDateCreated(new Date());
    buildAndUpdate();
}

protected void buildAndUpdate(){
    //populate map here
}

final Date getDateCreated() {
    return dateCreated;
}

final void setDateCreated(Date dateCreated) {
    this.dateCreated = dateCreated;
}

final long getExpiration() {
    return expiration;
}

final void setExpiration(long expiration) {
    this.expiration = expiration;
}

Comments

0

What I ended up doing is I moved the class that managed all the Cache objects in another package. I liked the idea of Inversion of Control though, makes the code looks smoother and modular - which is why I marked it as the best answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.