文章目录
设计模式的三大原则
- 单一职责原则。通俗地讲就是一个类只做一件事
CALayer:动画和视图的显示。
UIView:只负责事件传递、事件响应。 - 开闭原则。对修改关闭,对扩展开放。
要考虑到后续的扩展性,而不是在原有的基础上来回修改 - 接口隔离原。 使用多个专门的协议、而不是一个庞大臃肿的协议 UITableviewDelegate
UITableViewDataSource - 依赖倒置原则。抽象不应该依赖于具体实现、具体实现可以依赖于抽象。 调用接口感觉不到内部是如何操作的
- 里氏替换原则。 父类可以被子类无缝替换,且原有的功能不受任何影响 例如 KVO
- 迪米特法则。 一个对象应当对其他对象尽可能少的了解,实现高聚合、低耦合
工厂的三种设计模式
简单工厂模式(Simple Factory Pattern)
专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常具有共同的父类。(总结来说就是把一大堆if-else判断由业务层放到工厂类里面)如果策划要加种类,你必须又加一个if-else的条件判断,这样会造成无休止的修改此类,然后再次测试此类能否正常运行,包括引用到它的类又能否正常运行。如果到后期系统越变越庞大,则非常难维护。这就是违背了开闭原则。
优点
- 将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
- 当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
- 在调用工厂类的工厂方法时,由于工厂方法是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可,修改参数时无须修改任何源代码
缺点
- 简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。
代码例子:
主界面设置一个TextField和一个button 然后在button的点击事件中调用工厂方法进行创建不同的类的实例
- (void)viewDidLoad {
[super viewDidLoad];
_testTextField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
_testTextField.backgroundColor = [UIColor grayColor];
[self.view addSubview:_testTextField];
_testButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_testButton setTitle:@"确定" forState:UIControlStateNormal];
[self.view addSubview:_testButton];
[_testButton setFrame:CGRectMake(200, 200, 200, 200)];
[_testButton addTarget:self action:@selector(pressButton) forControlEvents:UIControlEventTouchUpInside];
}
- (void)pressButton {
id whichOne = [SimpleFactory createCalcute:_testTextField.text];
[whichOne calculate];
//为了方便判断,采用协议,来用不同的类重写协议中的方法。从而实现不同类的判断
}
创建一个工厂 工厂通过传递的NSString*类型的值进行判断所属类型从而创建类的实例 我这里通过简单的判断是否为加减乘除进行判断 创建对应实例
+ (id)createCalcute:(NSString *)calculatetype {
NSArray *calculateArray = @[@"+",@"-",@"*",@"/"];
switch ([calculateArray indexOfObject:calculatetype]) {
case 0:
return [[AddOfSimple alloc]init];
break;
case 1:
return [[MinusOfSimple alloc]init];
break;
case 2:
return [[MultiplyOfSimple alloc]init];
break;
case 3:
return [[DivideOfSimple alloc]init];
}
return NULL;
}
工厂方法模式(Factory Method Pattern)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到了子类。就像Cocoa Touch中的NSNumber的numberWithBool和numberWithInt方法,他们传入不同类型的参数,获得NSNumber实例。
什么时候使用?
- 编译时无法准确预期需要创建对象的类。
- 类想要其子类决定在运行时创建什么类型的实例。
- 类有若干辅助类为其子类,而你想将返回哪个子类这种信息局部化。
优势
和直接创建具体对象相比,使用工厂方法创建对象算是最佳的做法。
工厂方法让客户端可以要求由工厂方法创建的对象拥有一组共同的行为。
因此,向类层次结构中引入新的具体产品并不需要修改客户端代码,因为返回的任何具体对象的接口跟客户端一直使用的接口相同。
源代码
相比于简单工厂模式,其使用对工厂的继承从而创造出其他的子工厂,在其子工厂进行创建类的对象,后续直接调用,该工厂的那个重写方法即可。
HCDfactory *factory = [[HCDfactoryAdd alloc]init];
HCDfactory *calculate = [factory createFactory];
calculate.numberA = 10;
calculate.numberB = 15;
NSLog(@"结果是%f",[calculate calculate]);
HCDfactory就是我们的主工厂,主工厂有四个子工厂分别是HCDfactoryAdd、HCDfactoryMinus、HCDfactoryDivide、HCDfactoryMultiply加减乘除四个字工厂,我们现在先在“加工厂”下申请一个变量 这个变量就相当于是这个工厂
然后通过调用“加工厂”下面重写的createFactory方法得到具体的实例,这就保证了一个类的实例化延迟到了子类。
- (id<HCDCalculate>)createFactory {
return [[HCDCalculateAdd alloc]init];
}
抽象工厂模式(Abstract Factory Pattern)
提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。
抽象工厂扩展了之后算不算违背了开闭原则?
代码示例
HCDFactory factory = [[HCDSqlserverFactory alloc]init];
HCDDepartment department = [factory createDepartment];
[department insertDepartment:[[SQLDepartment alloc]init]];
[department getDepartment];
HCDFactory factory1 = [[HCDAccessFactory alloc]init];
HCDDepartment department1 = [factory1 createDepartment];
[department1 insertDepartment:[[SQLDepartment alloc]init]];
[department1 getDepartment];
我们可以看到 抽象工厂与工厂模式不同,抽象工厂的创建方式是对象组合创建抽象产品,而不是工厂模式中的类继承创建抽象产品
为什么说是组合创建抽象产品,我们可以看到每个不同的工厂里都有两种不同的创建方法,得到不同的对象,我们可以根据我们需要来得到我们所需要的对象,就可以理解为
抽象工厂模式把产品进行了两个纬度的划分,其中一个纬度是从产品本身派生出来的,鼠标、键盘、麦克风这些产品类别的划分。另外一个纬度是从工厂派生出来的,有不同品牌的工厂。
而工厂模式只有一个纬度,产品和工厂是完全对应的。