Trouble with Decorator Pattern, iOS / UICollectionViewCells


I am trying to 'decorate' UICollectionViewCells using the Decorator pattern.

For example, if I have a

 BaseCell : UICollectionViewCell

I would like to be able to do something like this:

 BaseCell *cell = [[BaseCell alloc] initWithFrame]
 cell = [[GlowingCell alloc] initWithCell:cell];
 cell = [[BorderedCell alloc] initWithCell:cell];
 cell = [[LabelledCell alloc] initWithCell:cell];

 // cell is now a glowing, bordered, labelled cell.

I think the Decorator pattern is pretty neat for this sort of thing, but I'm having difficulty applying it to collection views.

Firstly, in UICollectionViewControllers you need to register a class, like this:

 [self.collectionView registerClass:cellClass forCellWithReuseIdentifier:cellIdentifier];

So I don't have an opportunity to make my own instance.

Secondly, I can't see how the Decorator can ever be useful for decorating 'non-pure' objects, that is, objects that I didn't create from the ground up but have their own properties and behaviours (such as UICollectionViewCell). Since in the example above, cell represents a new instance of LabelledCell, and if UICollectionView makes a call on a method, eg, isSelected, this will call aLabelledCellInstance.isSelected unless I specifically do this in my Decorator base class:

 - (BOOL)isSelected {
      return self.decoratedCell.isSelected;

Which is fine for one method but it doesn't seem right to have to override every method in UICollectionViewCell. Should I be using forwardInvocation:?

Am I abusing this pattern, and are there alternatives? Because it works very nicely in books when you just have to override basic methods like

 getPrice() {
      return decoratedObject.getPrice() + 1.10f;

.. but seems hard to fit to the purpose of actually decorating existing UI elements with custom behaviour.


EDIT: What I am trying to avoid is having classes like this:

  • GlowingBorderedCell
  • LabelledGlowingBorderedCell
  • etc.

On paper the Decorator is the perfect candidate for what I am trying to achieve but the implementation is absolutely stumping me.

Firstly, the Decorator pattern requires you to override all the base methods in the BaseDecorator so you can forward the calls to the decorated object. And you can do this either by overriding every single method or, preferably, just use forwardInvocation:. And since all other decorators will be subclasses of BaseDecorator, you can now just override the methods you want to change.

Secondly, for the CollectionView issue, I suggest to use the Decorator pattern with normal UIViews, and then use the decorated view as the contentView of the cell. Let's see an example:

We have BaseCellView class which will be the super class for all decorators.

BaseCellView : UIView;
GlowingCellView: BaseCellView;
BorderedCell: BaseCellView;
LabelledCell: BaseCellView;

And we still have our BaseCell class which is a subclass of UICollectionViewCell:

BaseCell : UICollectionViewCell;

Now, UICollectionViewControllers will always create an instance of BaseCell and give you the chance to configure it, where you'll do the following:

BaseCellView *cellView = [[BaseCellView alloc] initWithFrame]
cellView = [[GlowingCellView alloc] initWithCellView:cellView];
cellView = [[BorderedCellView alloc] initWithCellView:cellView];
cellView = [[LabelledCellView alloc] initWithCellView:cellView];
cell.contentView = cellView;

And you still can forward any UICollectionViewCell to the decorator if you want that.