设计模式-面向对象

144 阅读4分钟

定义

  • 面向对象编程(OOP,Object Oriented Programming),以类(Class)和对象(Object)作为组织代码的基本单元(广义定义),并将封装,抽象,继承,多态四个特性作为代码设计和实现的基石(严格定义);
  • 面向对象编程语言(OOPL,Object Oriented Programming Language),支持类或对象的语法机制,能够方便实现面向对象编程的四大特性;
  • 面向对象分析(OOA,需求分析),面向对象设计(OOD,系统设计),面向对象编程(OOP)是面向对象编程的三个重要阶段。OOA和OOD产出类的详细设计供OOP使用。
  • 统一建模语言(UML,Unified Model Language),用于开发过程中绘制类图、例图、顺序图、活动图、状态图、组件图等。

主要特性

面向对象编程的四大特性为:封装,抽象,继承,多态

  • 封装(Escapsulation),信息隐藏或数据访问保护
    • 实现封装的语法机制为访问权限控制
    • 访问权限控制降低了灵活性,但显著提高了可控性
    • 访问权限控制提高了易用性
/**
Wallet.h
**/
@interface Wallet : NSObject

@property (nonatomic, strong, readonly) NSString *id; // 只读,不允许修改
@property (nonatomic, assign, readonly) NSTimeInterval *createTime; // 只读,不允许修改
@property (nonatomic, assign, readonly) NSInteger balance; // 只读,允许间接修改
@property (nonatomic, assign, readonly) NSTimeInterval *lastModifiedTime;  // 只读,允许间接修改

// 存入金额
- (void)increaseBalance:(NSInteger)increased;
// 取出金额
- (NSInteger)decreaseBalance:(NSInteger)decreased;

@end

```objective-c
/**
Wallet.m
**/
@interface Wallet ()

@property (nonatomic, strong, readwrite) NSString *id;
@property (nonatomic, assign, readwrite) NSTimeInterval *createTime;
@property (nonatomic, assign, readwrite) NSInteger balance;
@property (nonatomic, assign, readwrite) NSTimeInterval *lastModifiedTime;

@end

@implementation

- (instancetype)init
{
    if (self = [super init])
    {
        self.id = [[IDGenerator getInstance] generate];
        self.createTime = [[NSDate date] timeIntervalSince1970];
        self.balance = 0;
        self.lastModifiedTime = [[NSDate date] timeIntervalSince1970];
    }
    return self;
}

- (void)increaseBalance:(NSInteger)increased
{
    self.balance += increased;
    self.lastModifiedTime = [[NSDate date] timeIntervalSince1970];
}

- (NSInteger)decreaseBalance:(NSInteger)decreased
{
    self.balance -= decreased;
    self.lastModifiedTime = [[NSDate date] timeIntervalSince1970];
}

@end
  • 抽象(Abstract)隐藏方法的实现,告知调用方类提供的功能;
    • 借助编程语言提供的接口类和抽象类实现;
    • 关注功能点而非设计思路,过滤非必要信息
    • 方法的定义和实现都需要有抽象思维

@protocol RACSubscriber <NSObject>

@required
- (void)sendNext:(nullable id)value;
- (void)sendError:(nullable NSError *)error;
- (void)sendCompleted;
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;

@end
  • 继承(Inheritance),用来表示类之间的IS-A关系
    • 存在两种模式:单继承和多继承
    • 有利于代码复用
  • 多态(Polymorphism),在代码运行过程中,子类可以替换父类,调用子类的方法实现
    • 多态实现的方法1:继承
    • 多态实现的方法2:接口类
    • 多态实现的方法3:Duck-Typing(鸭子类型)
// 基于继承的多态
// Parent Class - Animal
@interface Animal : NSObject

- (void)run;

@end

@implementation Animal

- (void)run
{
    NSLog(@"I can run.");
}

@end

// Child Class - Cat
@interface Cat : Animal
@end

@implementation Cat

- (void)run
{
    NSLog(@"I can run with my four legs.");
}

@end

// Child Class - Duck
@interface Duck : Animal
@end

@implementation Duck

- (void)run
{
    NSLog(@"I can run with my two legs.");
}

@end

// 
@interface TestViewController : UIViewController
@end

@implementation TestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSMutableArray<Animal *> *animals = @[].mutableCopy;
    Duck *duck = [[Duck alloc] init];
    [animals addObject:duck];
    Cat *cat = [[Cat alloc] init];
    [animals addObject:cat];
    for (Animal *animal in animals)
    {
        [animal run];
    }
}

@end

// 基于接口类的多态
@protocol AnimalWithLegs <NSObject>

@required
- (void)run;

@end

// Class - Cat
@interface Cat : NSObject <AnimalWithLegs>
@end

@implementation Cat

- (void)run
{
    NSLog(@"I can run with my four legs.");
}

@end

// Class - Duck
@interface Duck : NSObject <AnimalWithLegs>
@end

@implementation Duck

- (void)run
{
    NSLog(@"I can run with my two legs.");
}

@end

// 
@interface TestViewController : UIViewController
@end

@implementation TestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSMutableArray<id<AnimalWithLegs>> *animals = @[].mutableCopy;
    Duck *duck = [[Duck alloc] init];
    [animals addObject:duck];
    Cat *cat = [[Cat alloc] init];
    [animals addObject:cat];
    for (id<AnimalWithLegs> animal in animals)
    {
        [animal run];
    }
}

@end


// 基于🦆类型的多态
class Logger: 
    def record(self): 
        print(“I write a log into file.”) 
        
class DB: 
    def record(self): 
        print(“I insert data into db. ”) 
        
def test(recorder): 
    recorder.record()
    
def demo(): 
    logger = Logger() 
    db = DB() 
    test(logger) 
    test(db)

面向过程 🆚 面向对象

  • 面向过程以过程(函数,Operator)作为组织代码的基本单元,主要特点是数据与方法分离,通过顺序拼接一组方法操作数据完成一项功能。
  • 面向对象比面向过程更适合大规模程序的开发;
  • 面向对象编程输出的代码更加易用,易扩展,易维护;
  • 面向对象编程语言更加高级,人性,智能;

导致面向对象退化的编程方式

  • 滥用getter && setter破坏封装特性
  • 滥用全局变量和全局方法
    • 全局变量:单例对象,静态成员变量,常量
    • 全局方法:静态方法
  • 定义数据和方法分离的类,如基于贫血模型的开发模式;

抽象类 🆚 接口

  • 基于抽象类可以实现:面向对象继承特性,模版设计模式,JAVA中的抽象类:

    • 抽象类只能继承,不能实例化
    • 抽象类可以定义属性和方法,无实现代码的方法叫抽象方法
    • 子类必须实现抽象类中的所有抽象方法
    • 相较普通的类,抽象类有利于提高代码可读性,鲁棒性,简洁性
  • 基于接口可以实现:面向对象抽象特性,面向对象多态特性,基于接口而非实现的设计原则,JAVA中的接口:

    • 接口不能包含属性
    • 接口只能声明方法,不能实现方法
    • 类必须实现接口中的所有方法
    • 接口侧重于解耦,提高代码灵活性,可扩展性
  • 抽象类是特殊的类,符合IS-A关系,接口表示一种HAS_A关系,JAVA中的接口和Objective-C中的协议类似;