8

我正在尝试使用装饰器模式来“装饰” UICollectionViewCells。

例如,如果我有一个

 BaseCell : UICollectionViewCell 

我希望能够做这样的事情:

 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.

我认为装饰器模式非常适合这类事情,但我很难将它应用到集合视图中。

首先,在 UICollectionViewControllers 中你需要注册一个类,像这样:

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

所以我没有机会制作自己的实例。

其次,我看不出装饰器如何用于装饰“非纯”对象,即我没有从头开始创建但具有自己的属性和行为的对象(例如 UICollectionViewCell)。由于在上面的示例中,cell表示 LabelledCell 的新实例,并且如果 UICollectionView 对方法进行调用,例如 ,除非我在我的 Decorator 基类中专门执行此操作,否则isSelected它将调用:aLabelledCellInstance.isSelected

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

这对于一种方法来说很好,但是必须覆盖UICollectionViewCell. 我应该使用forwardInvocation:吗?

我是否在滥用这种模式,还有其他选择吗?因为当您只需要覆盖基本方法时,它在书籍中非常有效,例如

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

.. 但似乎很难达到用自定义行为实际装饰现有 UI 元素的目的。

谢谢

编辑:我试图避免的是有这样的课程:

  • 发光边框单元格
  • 标记发光有界细胞
  • 等等

在纸面上,装饰器是我想要实现的目标的完美候选者,但实现绝对让我难过。

4

2 回答 2

4

首先,装饰器模式要求你重写所有的基方法,BaseDecorator这样你就可以将调用转发给被装饰的对象。您可以通过覆盖每个方法来做到这一点,或者最好只使用forwardInvocation:. 并且由于所有其他装饰器都是 的子类BaseDecorator,因此您现在可以覆盖您想要更改的方法。

其次,对于这个CollectionView问题,我建议使用带有普通UIViews的Decorator模式,然后使用装饰视图作为contentView单元格的。让我们看一个例子:

我们有一个BaseCellView类,它将成为所有装饰器的超类。

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

我们仍然有我们的BaseCell类,它是以下的子类UICollectionViewCell

BaseCell : UICollectionViewCell;

现在,UICollectionViewControllers将始终创建一个实例BaseCell并让您有机会对其进行配置,您将在其中执行以下操作:

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

如果您愿意,您仍然可以将任何内容转发UICollectionViewCell给装饰者。

于 2013-02-01T19:21:48.363 回答
3

是我在其中描述了这种技术的帖子。虽然我选择了装饰UITableView而不是单元格,但它可以很容易地适应您的收藏视图。这是一篇很长的文章,所以我在这里只做一个简短的总结:

  • 装饰器需要是代理对象才能将所有消息转发到装饰对象
  • 您需要在装饰器中覆盖多种方法才能实现这一点,其中respondsToSelectorforwardingTargetForSelector
  • 完成后,您将能够链接非常整洁的装饰器:

例如:

dec = [[DEFooterDecorator alloc] initWithDecoratedObject:dec];
dec = [[DEHeaderDecorator alloc] initWithDecoratedObject:dec];
dec = [[DEGreenCellDecorator alloc] initWithDecoratedObject:dec];
于 2013-02-01T19:34:05.367 回答