今日、我々はADTと、私をたくさん作る私たちのiOSプロジェクトをチェックアウトする能力について、抽象クラスについて説明し、「コードコンプリート第2版、」を参照してください、すぐに、次のような悪い味(悪い良いクラス・インタフェース・デザイン)を見つけます私の改善を共有しています。(ここでは、クラスの名前の実際のプロジェクトでは、クラス名が変更されているではありません)
改善前:
これは、カスタムセルクラスです。
@protocol CustomCellDeletage <NSObject>
- (void)checkDidTouch:(CustomCell *)cell;
@end
@interface CustomCell : UITableViewCell
@property (nonatomic, weak)id<CustomCellDeletage> delegate;
@property (nonatomic, retain)UIButton * checkBtn;
//这里直接暴露了类的成员变量细节,导致类对自身内部控制的松动,按钮的状态改变将难以追踪,并且这个类和按钮对象如何使用也会让调用方摸不着头脑,这次的改动将以此为重
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
_checkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkBtn addTarget:self action:@selector(checkBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
//...省略部分代码
}
return self;
}
- (void)checkBtnPressed:(id)sender {
// 切换选中状态
_checkBtn.selected = !_checkBtn.selected;
if (self.delegate && [self.delegate respondsToSelector:@selector(checkDidTouch:)]) {
[self.delegate checkDidTouch:self];
}
}
复制代码
外部コントローラの呼び出し:
cell.checkBtn.selected = [self isChecked:orderDict[@"orderId"]];
复制代码
外部コントローラコールバック:
#pragma mark CustomCellDeletage ---- 点击选择按钮事件
- (void)checkDidTouch:(CustomCell *)cell {
// 如果是选中状态,就添加 反之这移除
if (cell.checkBtn.selected) {
[self.checkArray addObject:cell.orderDict];
} else {
[self.checkArray removeObject:cell.orderDict];
}
[self updateViewInfo];
}
复制代码
行うため、ここでのコード評価「コードコンプリート第2版、」本の著者は、ADTの利点について説明します。ここでのメンバ変数checkBtnクラスに直接さらさなどと被害の多くをもたらしました。
ADT(抽象データ型)
- 実装の詳細を隠します
データ型が変更された場合、あなただけのプログラムの他の部分に影響を与えることなく、1を変更する必要があります。ここでは、例えば、UIButton UISwitchのタイプは、唯一の特定のインターフェイスを実現するために変更する必要がある場合は、インターフェイスの発信者に影響を与えることなく、
- インターフェースは、より多くの情報を提供することができるように、プログラムはより自明です
ここでは、例えば、改善されたインターフェースselectOnクラス及びメソッドのセットの後ろより意味のある説明をselectOff
抽象
- それ以降に抽象の具体的な実装を提供するインタフェースクラスを隠します
- クラスのインターフェイスは、抽象化の同じレベルを示さなければなりません
ここで、このような細胞クラスなどの細胞、選択された細胞を提供し、セルインターフェースのチェックを外し、直接メンバ変数を露出してはなりません
- そして、メンバーは、包装のアクセシビリティを向上させることが可能な限り制限します
- 公開データのメンバーを公開しないでください。
- プライベート実装の詳細クラスにインターフェースを避けます
変更の核となるアイデア
分離サブルーチンのセットに対してボタンの操作ボタンを操作するために必要な他のプログラムのより良好な抽象化レイヤ部、およびプロパティの変更の操作状態ボタンの保護層を提供することができます。基本となる実装でそれを操作するのではなく、現実の世界で動作しているエンティティのように
改善します
@protocol CustomCellDeletage <NSObject>
- (void)customCellDidSelectOn:(CustomCell *)cell;
- (void)customCellDidSelectOff:(CustomCell *)cell;
@end
@interface CustomCell : UITableViewCell
@property (nonatomic, weak)id<CustomCellDeletage> delegate;
- (void)selectOn;
- (void)selectOff;
@end
@interface CustomCell ()
@property (nonatomic, strong)UIButton * checkBtn;
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
_checkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkBtn addTarget:self action:@selector(checkBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
//...省略部分代码
}
return self;
}
- (void)checkBtnPressed:(id)sender {
if (_checkBtn.selected) {
[self selectOff];
if (self.delegate && [self.delegate respondsToSelector:@selector(customCellDidSelectOff:)]) {
[self.delegate customCellDidSelectOff:self];
}
} else {
[self selectOn];
if (self.delegate && [self.delegate respondsToSelector:@selector(customCellDidSelectOn:)]) {
[self.delegate customCellDidSelectOn:self];
}
}
}
- (void)selectOn {
_checkBtn.selected = YES;
}
- (void)selectOff {
_checkBtn.selected = NO;
}
@end
复制代码
外部コントローラの呼び出し:
if ([self isChecked:orderDict[@"orderId"]]) {
[cell selectOn];
} else {
[cell selectOff];
}
复制代码
外部コントローラコールバック:
#pragma mark <CustomCellDelegate>
- (void)customCellDidSelectOn:(CustomCell *)cell {
[self.checkArray addObject:cell.orderDict];
[self updateViewInfo];
}
- (void)customCellDidSelectOff:(CustomCell *)cell {
[self.checkArray removeObject:cell.orderDict];
[self updateViewInfo];
}
复制代码
変更はポイント:
- 私有財産のクラスとして、ボタン
- ボタンではなく、ボタンオブジェクトの低レベルの詳細に直接接触よりも、セルを、運営組織のように、現実の世界のように、よりに抽象化抽象化selectOnとselectOffインタフェースの高いレベルを提供するためにパッケージ化され、選択したオブジェクトの状態を変更するセルを選択してチェックを外します選択されたプロパティは、YESまたはNOに設定されています。
- 抽象インタフェースselectOnとselectOffメソッド呼び出し側は、実装の詳細を気にすることなく、より高いレベル、より説明的な意味を呼び出します。複数の局所的な変化に外観を変更する必要がないので、内部細胞はまた、この方法により、外観を変更することができます。
- より多くの単一のコールバックメソッドの任務、それは小切手またはオフにした後、選択された他に対処するかもしれない追加した後、機能の複雑さを軽減している場合を取り除く、今の二つの方法に分け、元のメソッドとの取引や未チェックで選択物事には、保守が容易になります。
- ボタンは、オブジェクトの別の型、またはより複雑なカスタムボタンのオブジェクトに置き換えられた後、オブジェクトの面では、それは単に、パッケージ内に内部的に実装変更するプログラムの他の部分に影響を与えません。
改善されたコード:
- クラスの改善、パッケージの実装の詳細を非表示にします
- クラスインターフェースとクラスは、抽象化の一貫性のレベルを維持するため
- より高いレベルのインタフェースの抽象クラス
- シングル責任
一部の学生は、これらの変更は、やることが必要であることを感じて、とても大きく道を得るが、各クラスはいつも、その後、複数の反復後に、抽象化の外部インタフェース一貫したレベルの高い度を維持されていない場合、私たちは常に、清潔で整然とコードを維持すべきであることクラスは維持するために、ますます理解することは困難と困難なこと、そして巨大なクラスは、新機能のバグは、我々は常にことを覚えておいてください古い増加した機能が関与して、無関係なデータとロジックの様々な簡単に続けあります
ない悪と小さな場面するのではなく、善を行います
ます。https://juejin.im/post/5cff4ecaf265da1b8d16136aで再現