图说设计模式(二)

创建型模式

关键之处是对类的实例化过程进行了抽象,将创建和对象的使用分裂,使得软件结构清晰,别人使用的时候,只需要知道使用接口,不需要知道具体实现细。包含的模式有简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式。

简单工厂模式(simple factory pattern)

如果有一个基类有很多子类继承,这个时候我想根据不同的参数创建不同的子类实例,可以构建一个工厂类,这个工厂类封装了不同的产品子类实例化方法,根据不同的参数选择实例化不同的对象,返回即可。

如图,产品A,产品B,由工厂类封装,提供方法,方法里面按照传入参数选择创建不同的产品类。

时序图如下:

使用工厂模式的优点:

创建和对象本身的业务处理分离,降低系统耦合度,使得修改相对容易

工厂方法是静态方法,传入的参数甚至可以放入xml等格式配置文件中,无须修改源代码。

存在的问题:

我如果要添加新的产品类,除了要增加产品类外,还需要修改工厂类里面的创建逻辑。

工厂方法模式(factory Methond Pattern)

这个是对简单工厂模式的改进,简而言之,之前是建一个工厂类负责所有产品的创建,现在则是改为一个抽象工厂类和几个工厂子类,由工厂子类去定义具体的方法生产产品类,如果有新的产品类,那么我们创建一个工厂子类再由工厂子类创建产品类即可。

那么这样总共包含四个角色:抽象产品,具体产品,抽象工厂,具体工厂

时序图如下:

模式分析:工厂模式与简单工厂模式最大的不同就是利用了面向对象的多态性,使得工厂类分为工厂抽象类与具体工厂类,前者提供一个公共接口,后者提供各个产品对象的具体创建过程,使用多态性,通过调用父类方法,由参数决定使用哪一个哪一个子类的具体实现。

实际例子:

日志记录器有多种记录方式,如文件记录、数据库记录等

日志的两种类,工厂的两个子工厂,都有对应的实现方法,时序图如下:

优点:使用多态性,由工厂自行决定创建何种产品,增加的新的产品子类只需要添加新的具体产品和具体工厂即可。

缺点:因为要写具体类两个,增加类的个数,一定程度增加了系统复杂性,引入了抽象层,增加了系统抽象性和理解难度。

抽象工厂模式(abstract factory)

现在存在一个问题,具体产品也是分等级的,所有产品子类不一定是并列的,子类工厂在这里进行扩展,不仅仅只生产一种产品,而是生产一类产品,称作产品族。

工厂方法模式中,一个工厂针对一个产品等级结构。

抽象工厂模式则需要面对多个产品等级结构,这写不同等级结构的产品可能存在相关或者依赖关系。

如图,抽象工厂提供了两个接口,子产品也提供了两个接口。

简单的来说,抽象工厂模式不就是提供了多个接口,针对了多个抽象类的子类进行实例化而已,与自身命名似乎没什么关系啊。

优点:一个子类工厂可能对应着多个抽象产品的子类产品,这样一组相关联的子类产品创建就是产品族,这有利于客户端使用使用同一产品族的对象,对客户端来说,可以根据环境选择不同的产品族,无须修改已有的产品。

缺点:增加新的产品对象的时候,改动较大,因为抽象工厂定义了所有可能被创建的产品合集,显然要扩展接口,这回导致所有接口修改,增加不便。

建造者模式

新的问题出现情况:我们设计的时候,要做一件事,往往分解成多个功能,设计成多个类/模块等,然后我们需要实现这个整体功能的时候,可能需要导入一些参数,可能需要按照一定的顺序对子功能类进行实例化,在我工作中,使用slam构图的时候,就是需要按照一定的顺序实例化数据共享模块/雷达数据读取模块/rbpf构图模块等。我自己的解决方法是在主函数中,按照条件一个个实例化。

现在这种建造者模式就是用来解决这些问题,怎么解决?

将一个复杂对象的构建与它的表示进行分离,使得同样的构建过程有不同的表示方法。

建造者模式又可以称呼为生成器模式;

模式结构:Builder:抽象建造者  ConcreteBuilder:具体建造者  Director:指挥者  Product:产品角色

其中,Director与基类Builder是聚合关系,ConcreteBuilder 继承,并实现复杂产品的构建。

时序图如下:

setBuilder()函数应该设置配置信息的,将builder指针传入director中

construct()则是根据配置信息构建产品

优点:用户不需要直到内部细节,使用相同的构建过程可以创建不同的产品对象,使用了多态性,无需修改原有代码。

缺点:如果产品差异性较大,就不是和这还总方式,如果产品内部变化复杂,可能导致需要定义很多具体建造者来实现这种变化,导致系统复杂。

适用环境:需要生成的产品对象有复杂的内部结构,通常包含有多个成员属性。

                生成的产品对象属性相互依赖,需要指定生成顺序

              对象的创建过程独立于创建该对象的类,在建造者模式还总引入指挥者类,将创建爱呢过程封装在指挥者类中,而不再建造者类中

             隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

这个也只是具体看看概念,具体还是需要找实例写写才能理解;

单例模式

这个单例模式自己用的最多,明显使用的需求就是着一个实例我只能有一个。

并且能提供全局访问方法;

这里我就不多说类,自己单例模式也看得比较多。

一般的写法就是将构造函数私有化,这样就不会自动调用,

然后定义一个静态指针,一个公有函数,用于调用构造函数创建一个实例对象,指针赋予静态指针,下一次调用的时候如果已经创建过,那么直接返回指针即可,这样就保证类类的单独化。

除此之外,考虑到线程安全/效率执行等问题,还有懒汉式/饿汉式等变种。具体可以百度一下。

猜你喜欢

转载自blog.csdn.net/CWY_007/article/details/81539240
今日推荐