Trouble with Decorator pattern, iOS / UICollectionViewCells

decorator, design-patterns, ios, iphone, uicollectionview

Solution

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 `UIView`s, 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.

Problem

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. Thanks 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.

Original source