设计模式—工厂方法模式

一、引入

1. 原因

简单工厂模式只提供一个工厂类,处于对产品类进行实例化的中心位置,知道每一个产品对象的创建细节,并决定何时实例化哪一个产品类。但当有新产品要加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这违背了“开闭原则”。 具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性。用工厂方法模式可以解决这一问题。

2.例子:

  1. 一个系统,按钮工厂类可以返回一个具体的按钮实例,如圆形按钮、矩形按钮、菱形按钮等。如果需要增加一种新类型的按钮,如椭圆形按钮,那么除了增加一个新的具体产品类之外,还需要修改工厂类的代码,这就使得整个设计在一定程度上违反了“开闭原则”。
  2. 对系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是**将具体按钮的创建过程交给专门的工厂子类去完成,先定义一个抽象的按钮工厂类,再定义具体的工厂类来生成圆形按钮、矩形按钮、菱形按钮等,它们实现在抽象按钮工厂类中定义的方法。**这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,更加符合“开闭原则”。

二、 模式介绍

1、基本介绍

又称为工厂模式,也叫虚拟构造器模式或者多态工厂模式。属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类
核心思想:定义一个创建对象的抽象方法,由子类决定要实例化的类。将对象的实例化推迟到子类。

2、模式结构

在这里插入图片描述
分为抽象层和具体实现层
抽象层:包括产品和抽象工厂,抽象工厂里有factoryMethod()方法,所有具体工厂都调用该方法从而产生具体的产品,返回抽象Product。
具体实现层:包括ConcreteProduct和ConcreteFactory;ConcreteFactory是对Factory的实现,通过factoryMethod()直接create具体的产品,然后通过Product产生。

3、适用场景

  1. 当一个类不知道它所需要的对象的类时:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
  2. 当一个类通过其子类来指定创建哪个对象时:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  3. 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
实例:

电视机工厂
将品牌设为抽象工厂,将原有的工厂进行分割,为每种品牌的电视机提供一个子工厂,海尔工厂专门负责生产海尔电视机,海信工厂专门负责生产海信电视机,如果需要生产TCL电视机或创维电视机,只需要对应增加一个新的TCL工厂或创维工厂即可,原有的工厂无须做任何修改,使得整个系统具有更加的灵活性和可扩展性。

三、优缺点

1、优点

  1. 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  2. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  3. 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

2、缺点

  1. 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  2. 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

四、应用案例

1、需求

订购披萨项目:1) 披萨的种类很多 2) 披萨的制作流程有 prepare,bake, cut, box 3) 完成披萨店订购功能
要求:
1)便于披萨种类的扩展,要便于维护
2)客户在点披萨时,可以点不同地区风格口味的披萨,比如 北京的奶酪pizza、北京的胡椒pizza

2、方案分析

1、使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、
LDPizzaSimpleFactory 等等。对于少量的地区风格这种方法是可以满足的,但是实际上地域风格有很多,会导致工厂类特别多,不利于软件的可维护性、可扩展性。即不适用项目规模比较大的情况
2、使用工厂方法模式
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值