【设计模式】工厂方法模式
0 简单工厂模式
0.0 简单工厂模式动机
考虑一个简单的软件应用场景,一个软件系统可提供多个外观不同按钮(如圆形、矩形按、菱形按钮等), 这些按钮都源自同一个父类,不过在继承父类后不同的子类修改了部分属性从而使得它们可呈现不同外观,如果希望在使用这些按钮时,不需要知道这些具体按钮类的名字,只需要知道表示该按钮类的一个参数,并提供一个调用方便的方法,把该参数传入方法即可返回一个相应的按钮对象,此时,就可以使用简单工厂模式。
0.1 模式定义
简单工厂模式(simple factory pattern):又称静态工厂方法(static factory method) 模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
0.2 模式结构
简单工厂模式包含如下角色:
- factory:工厂角色
- 工厂角色负责实现创建所有实例的内部逻辑
- product:抽象产品角色
- 抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
- concreteproduct:具体产品角色
- 具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
-
0.3 简单工厂模式的缺点
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
- 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构
1.工厂方法模式(factory method pattern)
1.1 模式动机
在简单工厂模式的例子中,设计一个按钮工厂类(父类)统一负责所有产品创建。
在工厂方法模式中,将具体按钮的创建过程,交给专门的工厂子类做。
先定义一个抽象的按钮工厂类,在定义具体的工厂类生成(圆形,矩形,菱形按钮),它们实现在抽象按钮工厂类中定义方法。
如果出现新的按钮类型,只需为此创建一个新的具体工厂类获得实例。
1.2 模式定义
工厂方法模式也叫虚拟构造器,也叫多态工厂模式。
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,
工厂子类负责生成具体的产品对象,这样做的好处:将产品类的实例化操作延迟到工厂子类中完成,即:通过工厂子类确定实例化骂一个具体产品。
1.3.模式结构
工厂方法模式包含如下角色:
- product:抽象产品
- concreteproduct:具体产品
- factory:抽象工厂
- concretefactory:具体工厂
1.4.模式分析
工厂模式的主要功能:核心的工厂类不再负责所有产品的创建,将具体的创建交给子类做,核心的工厂类只负责给出具体工厂必须实现的接口,不负责哪一个产品类被实例化的细节,即可达到不修改工厂角色的情况下引入新产品。
工厂父类:定义创建产品对象的公共接口;
工厂子类:负责生成具体的产品对象;子类决定具体实例化哪一个具体产品类;
1.5 适用环境
- 一个类不知道它所需要的对象的类
- 一个类通过其子类来指定创建哪个对象
- 将创建对象额任务交给多个工厂子类的某一个
1.6 模式扩展
- 适用多个工厂方法:在抽象工厂角色中定义多个工厂方法,实现不同的业务逻辑
- 产品对象的重复使用:工厂对象将一个已经创建过的产品保存在一个集合(数组、list),根据用户请求对集合进行查询。如果没有想要的对象,就创建一个并且加入到集合中在返回给用户。
2.单例模式(singleton pattern)
2.1 模式定义
单例模式确保某一个;类只有一个实例,并自行实例化向整个系统提供该实例,该类成为单例类,它提供全局访问方法。
单例模式的三个要点:
- 某一个类只能有一实例
- 它必须能自行创建这个实例
- 它必须自行向整个系统提供这个实例
2.2 模式结构
- singleton: 单例
2.3 模式分析
单例模式保证一个类只有一个实例,单例类拥有一个私有构造器,确定用户无法通过new关键字直接实例化它,该模式中包含一个静态私有成员变量与一个静态公有的工厂方法,该方法负责检查实例的存在性和实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。
单例模式实现的过程需要注意:
- 单例类的构造函数为私有;
- 提供一个自身的静态私有成员变量;
- 提供一个公有的静态工厂方法。
2.4 实例
在os中,打印池是一个用于管理打印任务的应用程序,通过打印池用户可删除,中止,或者改变打印任务的优先级,在一个os中只允许运行一个打印池对象,如果重复创建打印池会抛出异常。
2.5 适用环境
- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
- 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式