美文网首页
设计模式

设计模式

作者: AlanGe | 来源:发表于2020-12-16 19:51 被阅读0次

    一、设计模式

    为解决特定场景下的问题而定制的解决方案.

    Demo

    设计模式简介

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。

    设计模式的使用

    设计模式在软件开发中的两个主要用途。

    • 开发人员的共同平台
      设计模式提供了一个标准的术语系统,且具体到特定的情景。例如,单例设计模式意味着使用单个对象,这样所有熟悉单例设计模式的开发人员都能使用单个对象,并且可以通过这种方式告诉对方,程序使用的是单例模式。

    • 最佳的实践
      设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。

    设计模式的分类

    根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)

    1. 创建型模式: 5种
      1、单例模式
      2、原型模式
      3、工厂模式
      4、抽象工厂模式
      5、建造者模式

    2. 结构型设计模式: 7种
      6、代理模式
      7、组合模式
      8、桥接模式
      9、享元模式
      10、外观模式
      11、装饰模式
      12、适配器模式

    3. 行为型设计模式:11种
      13、观察者模式
      14、访问者模式
      15、中介者模式
      16、解释器模式
      17、策略模式
      18、迭代器模式
      19、命令模式
      20、状态模式
      21、备忘录模式
      22、模板方法模式
      23、责任链模式

    二、设计模式的几大基本原则

    设计模式的原则:构建可复用,可维护代码的经验法则.

    1、接口隔离原则:接口里面只做必要的事情,不做其他相关的事情.

    2、开闭原则:对模块扩展开放, 对修改关闭。 .m里面的实现代码不改变

    3、里氏代换原则:任何类可以出现的地方, 子类一定可以出现, 子类跟父类可以相互替换,子类可以用父类所有的方法.

    多态:重写父类方法.

    里氏代换原则::尽量不要重写父类本身实现的逻辑.

    4、依赖倒转原则:抽象不依赖于细节,细节依赖于抽象.(一般值的是接口)

    5、聚合原则:需要从一个类扩展出另外一种方法,尽量不要使用继承,使用新的方法.

    6、最小知识原则::两个类没有彼此直接通信. 而是使用另一个类来通信

    7、单一职责原则: 一个类只负责一个功能领域(一个登陆的model,只负责登陆模块的数据)

    设计原则案例

    1、接口隔离原则:接口里面只做必要的事情,不做其他相关的事情.

    如:UITableViewDelegate、UITableViewDataSource
    需求:封装创建一个button,但按钮的尺寸由我自己控制

    @interface BaseView : UIView
    
    @property (nonatomic, strong) UIButton *btnPrint;
    
    // 1、接口隔离原则
    // 1、客户端不应该依赖它不需要的接口。
    // 2、类间的依赖关系应该建立在最小的接口上。
    // 接口里面只做必要的事情,不做其他相关的事情.
    - (void)changeBtnFrame:(CGRect)frame;
    
    // 违背了接口隔离原则
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor;
    
    @end
    
    #import "BaseView.h"
    
    @implementation BaseView
    
    // 接口隔离原则
    // 1、客户端不应该依赖它不需要的接口。
    // 2、类间的依赖关系应该建立在最小的接口上。
    // 接口里面只做必要的事情  不做其他相关的事情.
    - (void)changeBtnFrame:(CGRect)frame {
        self.btnPrint = [[UIButton alloc] initWithFrame:frame];
        [self.btnPrint setTitle:@"打印" forState:UIControlStateNormal];
        [self.btnPrint setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.btnPrint setBackgroundColor:[UIColor redColor]];
        [self.btnPrint addTarget:self action:@selector(btnPrintClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.btnPrint];
    }
    
    - (void)btnPrintClick {
        NSLog(@"点击事件");
    }
    
    // 违背了接口隔离原则
    // 抽象方法(声明了这个方法,但是不实现)
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor {
        
    }
    
    @end
    

    2、开闭原则:对模块扩展开放, 对修改关闭。 .m里面的实现代码不改变

    #import "BaseView.h"
    
    // 2、开闭原则: 对模块扩展开放, 对修改关闭。  .m里面的实现代码不改变
    // 继承自BaseView
    
    @interface FirstView : BaseView
    
    @property (nonatomic, copy) NSString *string;/**<  添加字符串 */
    
    /// 设置按钮的文字
    /// @param frame frame
    /// @param title 标题
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title;
    
    @end
    
    #import "FirstView.h"
    
    @implementation FirstView
    
    // 父类的方法
    - (void)changeBtnFrame:(CGRect)frame {
        
    }
    
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor {
        
    }
    
    /// 设置按钮的文字
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title {
        
    }
    
    @end
    

    3、里氏代换原则:任何类可以出现的地方,子类一定可以出现, 子类跟父类可以相互替换,子类可以用父类所有的方法.

    多态:重写父类方法.

    里氏代换原则:尽量不要重写父类本身实现的逻辑.

    父类可以被子类无缝替换,且原有功能不受任何影响
    kvo就使用了里氏替换原则
    kvo除了使用观察者模式,同时也遵从了里氏替换原则。

    BaseView

    #import <UIKit/UIKit.h>
    
    @interface BaseView : UIView
    
    @property (nonatomic, strong) UIButton *btnPrint;
    
    @property (nonatomic, copy) NSString *string;/**<  添加字符串 */
    
    // 1、接口隔离原则
    // 1、客户端不应该依赖它不需要的接口。
    // 2、类间的依赖关系应该建立在最小的接口上。
    // 接口里面只做必要的事情  不做其他相关的事情.
    - (void)changeBtnFrame:(CGRect)frame;
    
    // 违背了接口隔离原则
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor;
    
    // 设置按钮的文字
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title;
    
    @end
    
    #import "BaseView.h"
    
    @implementation BaseView
    
    // 接口隔离原则
    // 1、客户端不应该依赖它不需要的接口。
    // 2、类间的依赖关系应该建立在最小的接口上。
    // 接口里面只做必要的事情  不做其他相关的事情.
    - (void)changeBtnFrame:(CGRect)frame {
        self.btnPrint = [[UIButton alloc] initWithFrame:frame];
        [self.btnPrint setTitle:@"打印" forState:UIControlStateNormal];
        [self.btnPrint setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.btnPrint setBackgroundColor:[UIColor redColor]];
        [self.btnPrint addTarget:self action:@selector(btnPrintClick) forControlEvents:UIControlEventTouchUpInside];
        
        self.btnPrint.frame = CGRectMake(0, 0, 50, 50);
        [self addSubview:self.btnPrint];
    }
    
    - (void)btnPrintClick {
        NSLog(@"点击事件");
    }
    
    // 违背了接口隔离原则
    // 抽象方法(声明了这个方法,但是不实现)
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor {
        
    }
    
    // 设置按钮的文字
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title {
        
    }
    
    @end
    

    SecondView

    #import "BaseView.h"
    
    // 3、里氏代换原则 : 任何类可以出现的地方, 子类一定可以出现, 子类跟父类可以相互替换,子类可以用父类所有的方法.
    // 里氏代换原则: 尽量不要重写父类本身实现的逻辑.
    // 多态:重写父类方法.
    @interface SecondView : BaseView
    
    // 里氏代换原则 : 子类这里不能有方法
    
    @end
    
    #import "SecondView.h"
    
    @implementation SecondView
    
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor {
        
    }
    
    // 设置按钮的文字
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title {
        self.btnPrint = [[UIButton alloc] initWithFrame:frame];
        [self.btnPrint setTitle:title forState:UIControlStateNormal];
        [self.btnPrint setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.btnPrint setBackgroundColor:[UIColor yellowColor]];
        [self.btnPrint addTarget:self action:@selector(btnPrintClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.btnPrint];
    }
    
    - (void)btnPrintClick {
        NSLog(@"打印");
    }
    
    @end
    

    4、依赖倒转原则:抽象不依赖于细节,细节依赖于抽象.(一般值的是接口)

    SecondView.m

    #import "SecondView.h"
    
    @implementation SecondView
    
    - (void)changeBtnFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor {
        
    }
    
    // 设置按钮的文字
    - (void)changeBtnFrame:(CGRect)frame title:(NSString *)title {
        self.btnPrint = [[UIButton alloc] initWithFrame:frame];
        [self.btnPrint setTitle:title forState:UIControlStateNormal];
        [self.btnPrint setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.btnPrint setBackgroundColor:[UIColor yellowColor]];
        [self.btnPrint addTarget:self action:@selector(btnPrintClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.btnPrint];
    }
    
    // 4、依赖倒转原则:抽象不依赖于细节,细节依赖于抽象。(一般指的是接口)
    - (void)btnPrintClick {
        [self printString];
    }
    
    - (void)printString {
        NSLog(@"打印");
    }
    
    @end
    

    5、聚合原则:需要从一个类扩展出另外一种方法,尽量不要使用继承,使用新的方法。

    新建一个类:ButtonView

    #import <UIKit/UIKit.h>
    #import "SecondView.h"
    
    @interface ButtonView : UIView
    
    // 设置属性
    @property (nonatomic, strong) SecondView *secondView;
    
    // 5、聚合原则:需要从一个类扩展出另外一种方法,尽量不要使用继承,使用新的方法.
    // 设置按钮的图片
    - (void)changeBtnFrame:(CGRect)frame backgroundImg:(UIImage *)img;
    
    @end
    
    #import "ButtonView.h"
    
    @implementation ButtonView
    
    // 设置按钮的图片
    - (void)changeBtnFrame:(CGRect)frame backgroundImg:(UIImage *)img {
        // 编写secondView的相关代码
    }
    
    
    @end
    

    6、最小知识原则::两个类没有彼此直接通信. 而是使用另一个类来通信

    7、单一职责原则: 一个类只负责一个功能领域

    比如:一个登陆的model,只负责登陆模块的数据
    又比如:系统为我们实现的CLLayer和UIView的关系,UIView只负责事件传递以及事件响应,而CLLayer专门负责动画以及视图的展示,实际上就利用了设计模式中的所遵从的单一职责原则。

    三、设计模式

    创建型模式: 5种

    软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。

    创建型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合的方式。

    创建型模式又分为对象创建型模式和类创建型模式。对象创建型模式处理对象的创建,类创建型模式处理类的创建。详细地说,对象创建型模式把对象创建的一部分推迟到另一个对象中,而类创建型模式将它对象的创建推迟到子类中。

    3.1、单例模式

    保证一个类只有一个实例,并且提供对这个实例的全局访问方式。

    单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

    + (id)sharedInstance
    {
        static MyClass *instance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[super allocWithZone:NULL] init];
        });
        return instance;
    }
    + (id)allocWithZone:(struct _NSZone *)zone{
        return [self sharedInstance];
    }
    - (id)copyWithZone:(nullable NSZone *)zone{
        return self;
    }
    
    3.2、原型模式

    使用原型实例指定要创建的对象类型,通过复制原型创建新的对象。

    原型模式创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。

    原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。

    #import <Foundation/Foundation.h>
    // 定义协议
    @protocol PrototypeCopyProtocol <NSObject>
    // 复制自己
    - (id)clone;
    @end
    
    #import <Foundation/Foundation.h>
    #import "PrototypeCopyProtocol.h"
    // 遵循协议
    @interface StudentModel : NSObject <PrototypeCopyProtocol>
    
    @property (nonatomic, copy)   NSString *name;
    @property (nonatomic, copy)   NSString *address;
    @property (nonatomic, strong) NSNumber *age;
    @property (nonatomic, strong) NSNumber *totalScore;
    
    // 复制自己
    - (id)clone;
    
    @end
    
    #import "StudentModel.h"
    
    @implementation StudentModel
    
    // 复制自己
    - (id)clone {
        StudentModel *student = [[[self class] alloc] init];
        student.name = self.name;
        student.age = self.age;
        student.address = self.address;
        student.totalScore = self.totalScore;
        
        return student;
    }
    
    @end
    
    #import "ViewController.h"
    #import "StudentModel.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 学生1
        StudentModel *stu1 = [[StudentModel alloc] init];
        stu1.name = @"张三";
        stu1.age = @(18);
        stu1.address = @"帝都";
        stu1.totalScore = @(99);
    
        // 学生2 - 通过原型模式copy
        StudentModel *stu3 = [stu1 clone];
        stu3.name = @"王五";
        
        NSLog(@"stu1 = %@",stu1);
        NSLog(@"stu3 = %@",stu3);
    }
    
    @end
    
    3.3、工厂模式

    允许一个类的实例化推迟到子类中进行。

    工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”[1]

    创建一个对象常常需要复杂的过程,所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。

    对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期,以及管理特定对象的创建和销毁的概念。

    3.3.1简单工厂模式

    简单工厂

    #import <Foundation/Foundation.h>
    #import "Fruits.h"
    #import "Apple.h"
    #import "Orange.h"
    #import "Banana.h"
    
    // 由于外面要传一个类型进来,所以要加一个枚举才行
    typedef NS_ENUM(NSInteger) {
        kApple,
    } FruitsType;
    
    @interface FruitsFactory : NSObject
    
    // 创造水果的工厂
    + (Fruits *)fruitsFactory:(FruitsType)type;
    
    @end
    
    #import "FruitsFactory.h"
    
    @implementation FruitsFactory
    
    + (Fruits *)fruitsFactory:(FruitsType)type {
        
        // 创建空的对象.在工厂方法里面进行水果的制造
        Fruits *fruits = nil;
        
        switch (type) {
            case kApple:
                fruits = [[Apple alloc] init];
                break;     
            default:
                break;
        }
        return fruits;
    }
    
    @end
    

    水果类

    #import <Foundation/Foundation.h>
    
    @interface Fruits : NSObject
    - (void)sweet; /**< 甜 */
    - (void)poorTaste; /**< 不好吃 */
    @end
    
    #import "Fruits.h"
    
    @implementation Fruits
    
    - (void)sweet {}
    
    - (void)poorTaste {}
    
    @end
    
    // 继承自父类,扩展了新方法,遵循开闭原则
    
    #import "Fruits.h"
    
    @interface Apple : Fruits
    
    // 私有方法
    - (void)freshApple; /**< 新鲜的苹果 */   // 开闭原则
    
    @end
    
    #import "Apple.h"
    
    @implementation Apple
    
    // 甜
    - (void)sweet {
        NSLog(@"Apple 非常甜");
    }
    
    // 不好吃
    - (void)poorTaste {
        NSLog(@"Apple 不好吃");
    }
    
    // 私有方法
    // 新鲜的苹果
    - (void)freshApple {
        NSLog(@"Apple 新鲜的苹果");
    }
    
    @end
    
    3.3.2、工厂方法

    Generator:相当于是一个工厂

    #import <Foundation/Foundation.h>
    #import "ColorView.h"
    
    @interface ColorViewGenerator : NSObject
    
    - (ColorView *)colorViewWithFrame:(CGRect)frame;
    
    @end
    
    #import "ColorViewGenerator.h"
    
    @implementation ColorViewGenerator
    
    - (ColorView *)colorViewWithFrame:(CGRect)frame {
        return [[ColorView alloc] initWithFrame:frame];
    }
    
    @end
    
    #import "ColorViewGenerator.h"
    #import "RedView.h"
    
    @interface RedViewGenerator : ColorViewGenerator
    
    @end
    
    #import "RedViewGenerator.h"
    
    @implementation RedViewGenerator
    
    - (ColorView *)colorViewWithFrame:(CGRect)frame {
        return [[RedView alloc] initWithFrame:frame];
    }
    
    @end
    
    3.4、抽象工厂模式

    提供一个创建相关或依赖对象的接口,而不指定对象的具体类。

    抽象工厂模式(英语:Abstract factory pattern)是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

    举个例子来说,比如一个抽象工厂类叫做DocumentCreator(文档创建器),此类提供创建若干种产品的接口,包括createLetter()(创建信件)和createResume()(创建简历)。其中,createLetter()返回一个Letter(信件),createResume()返回一个Resume(简历)。系统中还有一些DocumentCreator的具体实现类,包括FancyDocumentCreatorModernDocumentCreator。这两个类对DocumentCreator的两个方法分别有不同的实现,用来创建不同的“信件”和“简历”(用FancyDocumentCreator的实例可以创建FancyLetterFancyResume,用ModernDocumentCreator的实例可以创建ModernLetterModernResume)。这些具体的“信件”和“简历”类均继承自抽象类,即LetterResume类。客户端需要创建“信件”或“简历”时,先要得到一个合适的DocumentCreator实例,然后调用它的方法。一个工厂中创建的每个对象都是同一个主题的(“fancy”或者“modern”)。客户端程序只需要知道得到的对象是“信件”或者“简历”,而不需要知道具体的主题,因此客户端程序从抽象工厂DocumentCreator中得到了LetterResume类的引用,而不是具体类的对象引用。

    “工厂”是创建产品(对象)的地方,其目的是将产品的创建与产品的使用分离。抽象工厂模式的目的,是将若干抽象产品的接口与不同主题产品的具体实现分离开。这样就能在增加新的具体工厂的时候,不用修改引用抽象工厂的客户端代码。

    使用抽象工厂模式,能够在具体工厂变化的时候,不用修改使用工厂的客户端代码,甚至是在运行时。然而,使用这种模式或者相似的设计模式,可能给编写代码带来不必要的复杂性和额外的工作。正确使用设计模式能够抵消这样的“额外工作”。

    3.5、建造者模式

    将一个复杂对象的创建与它的表示分离,使同样的创建过程可以创建不同的表示。
    将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

    构造者时序图
    建造者模式

    结构型设计模式: 7种

    3.6、代理模式

    为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

    代理模式1 代理模式

    协议:定义代理和委托的共同接口(方法)
    委托:根据指定的协议,委托代理去完成实现指定接口(方法)
    代理:根据指定的协议,实现委托需要实现的接口(方法)

    3.7、组合模式

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
    这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

    组合模式
    3.8、桥接模式

    将抽象部分与它的实现部分分离,使它们都可以独立地变化。
    抽象层与实现层相分离,抽象层定义了供客户端调用的抽象接口,实现层提供了具体的逻辑。实现类的引用被封装到抽象层的实例中,桥接就形成。

    桥接模式

    桥接模式的特点:

    1. 将依赖具体的实现,改为依赖抽象。得到松耦合的状态
    2. 分离了接口和实现部分
    3. 提高了扩展性
    3.9、享元模式

    使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件,简单来说就是相同数据拿来共享。

    享元模式

    享元模式:
    1.可共享享元对象.
    2.享元池

    3.10、外观模式

    为系统中的一组接口提供一个统一的接口。外观定义一个高层接口,让子系统更易于使用

    外观模式 外观模式2
    3.11、装饰模式

    装饰模式:动态的给一个对象添加一些额外的职责. 就扩展功能来说, 装饰模式相比生成子类更为灵活

    特点:
    1.不会改变原始类
    2.不改变使用继承
    3.扩展对象的功能

    装饰模式
    3.12、适配器模式

    类适配器:通过继承来适配两个接口
    对象适配器:不继承被适配者, 他们是一个关联关系,相当于引用了这个类

    对象适配器模式 类适配器模式

    总结
    适配器模式: 1.目标协议 2.适配者 3.适配器
    1.类适配器: 适配器是继承咋们适配者的
    2.对象适配器: 适配器是引用咱们的适配者的

    桥接模式跟适配器的区别:
    适配器: 改变已有的两个接口, 让他们相兼容. (组件之间的适配, 音视频方面, SDK跟自己写的代码之间适配)
    桥接模式:分离抽象化和实现类. 两者的接口可以不同,主要是在于分离
    桥接模式先有桥, 才有两端的实现.
    适配器模式是先有两边的, 才有适配器

    行为型设计模式:11种

    3.13、观察者模式

    观察者模式(有时又被称为模型-视图(View)模式、源-收听者(Listener)模式或从属者模式),一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

    观察者模式
    3.14、访问者模式

    访问者模式是一种将算法与对象结构分离的软件设计模式

    这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。

    3.15、中介者模式

    中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。

    中介者模式
    3.16、解释器模式

    实作特制化的编程语言以解决一系列特殊的问题。
    实现了一个表达式接口,该接口解释一个特定的上下文。

    3.17、策略模式

    定义一系列的算法,并且将每个算法封装起来,算法之间还可以互相替换。这种设计模式称为策略模式。

    策略设计模式
    3.18、迭代器模式

    提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。

    迭代器模式
    3.19、命令模式

    提供了一种封装方法调用细节的机制,基于这种机制我们可以实现延迟方法调用或者替换调用该方法的组件。

    命令模式
    3.20、状态模式

    允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
    在执行可以部分改变物件的一种方法。

    3.21、备忘录模式

    在不破坏一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态

    备忘录模式
    3.22、模板方法模式

    一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。


    模板模式
    3.23、责任链模式

    避免将一个请求的发送者与接收者耦合在一起, 让多个对象都有机会处理请求. 将接收请求的对象连接成一条链, 并且沿着这条链传递请求, 直到有一个对象能够处理它为止

    责任链模式

    相关文章

      网友评论

          本文标题:设计模式

          本文链接:https://www.haomeiwen.com/subject/owkogktx.html