装饰模式,iOS/UICollectionViewCells的麻烦

Sam*_*Sam 8 iphone design-patterns decorator ios uicollectionview

我试图使用Decorator模式'装饰'UICollectionViewCells.

例如,如果我有

 BaseCell : UICollectionViewCell 
Run Code Online (Sandbox Code Playgroud)

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

 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.
Run Code Online (Sandbox Code Playgroud)

我认为Decorator模式对于这类事情来说非常简洁,但是我很难将它应用于集合视图.

首先,在UICollectionViewControllers中,您需要注册一个类,如下所示:

 [self.collectionView registerClass:cellClass forCellWithReuseIdentifier:cellIdentifier];
Run Code Online (Sandbox Code Playgroud)

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

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

 - (BOOL)isSelected {
      return self.decoratedCell.isSelected;
 }
Run Code Online (Sandbox Code Playgroud)

对于一种方法来说哪个好,但是必须覆盖每个方法似乎都是正确的UICollectionViewCell.我应该用forwardInvocation:吗?

我是否滥用这种模式,还有其他选择吗?因为当你必须覆盖像这样的基本方法时,它在书籍中的效果非常好

 getPrice() {
      return decoratedObject.getPrice() + 1.10f;
 }
Run Code Online (Sandbox Code Playgroud)

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

谢谢

编辑:我想避免的是这样的课程:

  • GlowingBorderedCell
  • LabelledGlowingBorderedCell
  • 等等

在纸面上,装饰师是我想要实现的目标的完美候选者,但实施绝对难以理解.

Hej*_*azi 4

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

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

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

BaseCellView : UIView;
GlowingCellView: BaseCellView;
BorderedCell: BaseCellView;
LabelledCell: BaseCellView;
Run Code Online (Sandbox Code Playgroud)

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

BaseCell : UICollectionViewCell;
Run Code Online (Sandbox Code Playgroud)

现在,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;
Run Code Online (Sandbox Code Playgroud)

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