views:

64

answers:

2

I have a collection of instances of class A. At some point an instance of A realizes that it should delete itself. I want to inform the collection of this, but I do not want A to know anything about the collection.

What is the best way to go about this? It seems to me like A knowing about the collection is very bad coupling, but if I am wrong let me know. Right now I'm thinking of using something like, an instance of A can fire an event, to which the collection is listening. Then when the event is caught by the collection, remove the instance that fired it.

Any ideas on this would be helpful, thanks

A: 

Putting in terms of design pattern you are describing the Observer pattern (AKA: Publish/subscribe).

Instance of A will hold a listener. When A is deleted A will invoke the onDelete method on the listener passing itself as the parameter. The collection will implement the listener interface.

Another alternative is the Chain-of-Responsibility pattern.

Itay
But in what you're describing, doesn't A have to know it is in a collection to invoke an OnDelete method?
David Stratton
yes I had thought of this but it seems like strong coupling.
Ori Cohen
A is coupled with an interface that defines an onDelete() method. It is not coupled with the collection itself.
Itay
+1  A: 

An event is probably the best solution.

If the collection is an unordered collection (ICollection in .NET) there is also another solution. You could add an IsDeleted-property to your class A, that you set to true then it gets deleted. In your collection class you could then pretend that the objects that has IsDeleted=true isn't there.

Something like this:

class A {
    public bool IsDeleted { get; set; }
}

class ACollection : ICollection<A> {
    private List<A> _innerList = new List<A>();

    #region ICollection<A> Members

    public void Add(A item) {
     _innerList.Add(item);
    }

    public void Clear() {
     _innerList.Clear();
    }

    public bool Contains(A item) {
     if(item.IsDeleted)
      return false;
     return _innerList.Contains(item);
    }

    public void CopyTo(A[] array, int arrayIndex) {
     throw new NotImplementedException();
    }

    public int Count {
     get {
      int count = 0;
      foreach(var item in _innerList) {
       if(!item.IsDeleted)
        count++;
      }
      return count;
     }
    }

    public bool IsReadOnly {
     get { return false; }
    }

    public bool Remove(A item) {
     return _innerList.Remove(item);
    }

    #endregion

    #region IEnumerable<A> Members

    public IEnumerator<A> GetEnumerator() {
     foreach(var item in _innerList) {
      if(!item.IsDeleted)
       yield return item;
     }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
     foreach(var item in _innerList) {
      if(!item.IsDeleted)
       yield return item;
     }
    }

    #endregion
}
Mikael Sundberg