JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。

模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?

解决方案:建立一个工厂来创建对象

实现:

一、引言

    1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。

2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。

3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。你需要指定某个具体的工厂才能生产车出来。

4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。

最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.

这就是工厂模式。

二、分类

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

1)简单工厂模式(Simple Factory)

2)工厂方法模式(Factory Method)

3)抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。

GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。

将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

三、区别

工厂方法模式:

一个抽象产品类,可以派生出多个具体产品类。

一个抽象工厂类,可以派生出多个具体工厂类。

每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:

多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。

一个抽象工厂类,可以派生出多个具体工厂类。

每个具体工厂类可以创建多个具体产品类的实例。

区别:

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。

工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

两者皆可。

四、简单工厂模式

建立一个工厂(一个函数或一个类方法)来制造新的对象。

分布说明引子:从无到有。客户自己创建宝马车,然后拿来用。

copy?

public BMW320 {

  • BMW320(){
  • System.out.println(
    }
  • BMW523 {
  • BMW523(){
  • System.out.println(
    }
  • Customer {
  • main(String[] args) {
  • BMW320 bmw320 =  BMW320();
  • BMW523 bmw523 =  BMW523();
  • }
  • }

客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车型号就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式

即我们建立一个工厂类方法来制造新的对象。如图:

产品类:

copy?

abstract BMW {

  • BMW(){
  • }
  • }
  • BMW320  BMW {
  • BMW320() {
  • System.out.println(
    }
  • BMW523  BMW{
  • BMW523(){
  • System.out.println(    }
  • }

工厂类:

copy?

public Factory {

  • BMW createBMW( type) {
  • (type) {
  • :
  • BMW320();
  • :
  • BMW523();
  • :
  • ;
  • }
  • ;
  • }
  • }

客户类:

copy?

public Customer {

  • main(String[] args) {
  • Factory factory =  Factory();
  • BMW bmw320 = factory.createBMW();
  • BMW bmw523 = factory.createBMW();
  • }
  • }

简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。

先来看看它的组成:

1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品

2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。

3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。

下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。

我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。

于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。

五、工厂方法模式

        工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。

工厂方法模式组成:

1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。

2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。

3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。

4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活
起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有
的代码。可以看出工厂角色的结构也是符合开闭原则的!

代码如下:

产品类:

copy?

abstract BMW {

  • BMW(){
  • }
  • }
  • BMW320  BMW {
  • BMW320() {
  • System.out.println(    }
  • }
  • BMW523  BMW{
  • BMW523(){
  • System.out.println(
    }

创建工厂类:

copy?

interface
}

  • FactoryBMW320  FactoryBMW{
  • BMW320 createBMW() {
  • BMW320();
  • }
  • }
  • FactoryBMW523  FactoryBMW {
  • BMW523 createBMW() {
  • BMW523();
  • }
  • }

客户类:

copy?

public Customer {

  • main(String[] args) {
  • FactoryBMW320 factoryBMW320 =  FactoryBMW320();
  • BMW320 bmw320 = factoryBMW320.createBMW();
  • FactoryBMW523 factoryBMW523 =  FactoryBMW523();
  • BMW523 bmw523 = factoryBMW523.createBMW();
  • }
  • }

工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。

以上就是简单工厂模式,工厂方法模式,抽象工厂模式在这里

例子背景:

随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。于是这个工厂开始生产空调和发动机,用来组装汽车。这时候工厂有两个系列的产品:空调和发动机。宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机。

概念:

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。

针对百度百科上对于抽象工厂模式的简介,结合本例如下:

当每个抽象产品都有多于一个的具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品(产品空调有两个具体产品空调A和空调B)。抽象工厂模式提供两个具体工厂角色(宝马320系列工厂和宝马230系列工厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。

抽象工厂模式代码

产品类:

copy?

//发动机以及型号  
public Engine {

  • }
  • EngineA  Engine{
  • EngineA(){
  • System.out.println(
    }
  • EngineBextends Engine{
  • EngineB(){
  • System.out.println(    }
  • }
  • Aircondition {
  • }
  • AirconditionA  Aircondition{
  • AirconditionA(){
  • System.out.println(    }
  • }
  • AirconditionB  Aircondition{
  • AirconditionB(){
  • System.out.println(
    }

创建工厂类:

copy?

//创建工厂的接口  
public AbstractFactory {

  • Engine createEngine();
  • Aircondition createAircondition();
  • }
  • FactoryBMW320  AbstractFactory{
  • Engine createEngine() {
  • EngineA();
  • }
  • Aircondition createAircondition() {
  • AirconditionA();
  • }
  • }
  • FactoryBMW523  AbstractFactory {
  • Engine createEngine() {
  • EngineB();
  • }
  • Aircondition createAircondition() {
  • AirconditionB();
  • }
  • }

客户:

copy?

public Customer {

  • main(String[] args){
  • FactoryBMW320 factoryBMW320 =  FactoryBMW320();
  • factoryBMW320.createEngine();
  • factoryBMW320.createAircondition();
  • FactoryBMW523 factoryBMW523 =  FactoryBMW523();
  • factoryBMW320.createEngine();
  • factoryBMW320.createAircondition();
  • }
  • }

关于抽象工厂模式与工厂方法模式的区别,这里就不说了,感觉多看几遍例子就能理解,还有很多提到的产品族、等级结构等概念,说了反而更难理解。

抽象工厂模式的起源

下面引用一段抽象工厂模式的起源:

抽象工厂模式的起源或者最早的应用,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。

在每一个操作系统中,都有一个视窗构建组成的构建家族。在这里就是Button和Text组成的产品族。而每一个视窗构件都构成自己的等级结构,由一个抽象角色给出抽象的功能描述,而由具体子类给出不同操作系统下的具体实现。

可以发现在上面的产品类图中,有两个产品的等级结构,分别是Button等级结构和Text等级结构。同时有两个产品族,也就是UNIX产品族和Windows产品族。UNIX产品族由UNIX
Button和UNIX Text产品构成;而Windows产品族由Windows Button和Windows Text产品构成。

系统对产品对象的创建需求由一个工程的等级结构满足,其中有两个具体工程角色,即UnixFactory和WindowsFactory。UnixFactory对象负责创建Unix产品族中的产品,而WindowsFactory对象负责创建Windows产品族中的产品。这就是抽象工厂模式的应用,抽象工厂模式的解决方案如下图:

显然,一个系统只能够在某一个操作系统的视窗环境下运行,而不能同时在不同的操作系统上运行。所以,系统实际上只能消费属于同一个产品族的产品。

在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统只能消费某一个产品族了。

总结:

无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了

博客:http://blog.csdn.net/jason0539(转载请说明出处)

时间: 2024-10-03 22:28:05

JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)的相关文章

Java设计模式(一) 简单工厂模式不简单

原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自Jason's Blog,原文链接 http://www.jasongj.com/design_pattern/simple_factory 简单工厂模式使用案例 有一种抽象产品--汽车(Car),同时有多种具体的子类产品,如BenzCar,BMWCar,LandRoverCar.类图如下 作为司机,如果要开其中一种车,比如BenzCar,最直接的做法是直接创建BenzCar的实例,并执行其drive方法,如下 package com.

JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)

简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实现添加新产品而不影响已有代码?工厂方法模式应运而生,本文将介绍另外一种工厂模式--工厂方法模式. 1 日志记录器的设计 Sunny软件公司欲开发一个系统执行日志记录器(Logger).该记录器能够通过多种途径保存系统的执行日志,如通过文件记录或数据库记录,用户能够通过改动配置文件灵活地更换日志记录方式. 在设

java设计模式(1)-------单例,工厂,值对象,装饰模式

      java设计模式(1) 先简单的介绍下设计模式吧:是一种解决问题的一种行之有效的思想:用于解决特定环境下.重复出现的特定问题的解决方案. 那为什么我们需要学习设计模式呢? 1.设计模式都是一些相对优秀的解决方案,很多问题都是典型的.有代表性的问题,学习设计模式,我们就不用自己从头来解决这些问题,相当于在巨人的肩膀上,复用这些方案即可,站的高看到远,就是要站在巨人的肩膀上把他们踩下去,嘿嘿. 2.设计模式已经成为专业人士的常用词汇,不懂不利于交流,能让你变得很牛逼哦. 3.能让你设计的

JAVA设计模式(13):行为型-责任链模式(Responsibility)

定义 将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求, 如果能则处理,如果不能则传递给链上的一个对象. 场景: 打牌时,轮流出牌 接力赛跑 大学中,奖学金审批 公司中,公文审批 开发中常见的场景: Java中,异常机制就是一种责任链模式.一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch. Javascript语言中,事件的冒泡和捕获机制.Java语言中,事件的处理采用观察者模式. Servlet开发中

Java设计模式之从[剪刀石头布AI策略]分析策略(Strategy)模式

策略模式是一个很easy的模式. 它定义一系列的算法,把它们一个个封装起来,而且使它们能够相互替换. 考虑到我在做一个剪刀石头布的游戏,能够和计算机对战. 计算机的难度等级分为2个等级:普通难度和无法战胜难度. 普通难度是指电脑会随机出石头.剪刀.布.而无法战胜难度是指电脑会"作弊".电脑会事先知道玩家出的是什么手势. 假设玩家出的是剪刀.那么电脑会出石头,玩家永远的无法取胜. 那么,这两个难度分别代表两种算法,为了使得它们可以被游戏的主类装载,它们都应该继承于同一个接口或类.并暴露出

[Java设计模式](一)怎样实现Singleton(单例)模式编程

单例模式是开发模式中最简单,最易于理解的一种模式.简单地说,它指的就是始终保持一个实例的意思.但是,Java的类是可以穿件多个实例的,那么,怎么实现呢? 顾名思义,单例模式就是只有一个实例.单例模式确保某一个类只有一个实例,这个类称为单例类,单例模式有3个要点: ①是某个类只能有一个实例: ②它必须自行创建这个实例: ③是它必须自行向整个系统提供这个实例.例如,一些资源管理器常常设计成单例模式. 在计算机系统中,需要管理的资源有很多,例如每台计算机可以有若干个打印机,但只能有一个打印控制器,以避

JAVA设计模式(14):行为型-中介者模式(Mediator)

场景 假如没有总经理.下面三个部门:财务部.市场部.研发部.财务部要发工资,让大家核对公司需要市场需要跟市场部和研发部通气:市场部需要接个新项目,需要研发部处理技术.需要财务部出资金.市场部跟各个部门打交道.虽然只有三个部门,但是关系非常乱. 实际上,公司都有总经理.各个部门有什么事情都通报到总经理这里,总经理再通知各个相关部门. 这就是一个典型的中介者模式 总经理起到一个中介.协调的作用 核心 如果一个系统中对象之间的联系呈现为网状结构,对象之间存在大量多对多关系,将导致关系及其复杂,这些对象

java使用lock实现一个简单的生产者和消费者模式

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Five { public static void main(String[] args) { final Service myService = new Service(); for(int i = 0 ; i < 10 ; i ++){ Thread thread = new Th

工厂模型简单的汽车工厂

代码: /** * Description:简单工厂模型(汽车工厂) * @author 李XX2019年9月21日 */ public class SimpleFactoryPattern { public static void main(String[] args) { Audi aAudi = new Audi(); aAudi.run(); Auto aAuto = new Auto(); aAuto.run(); System.out.println("-------------&q

设计模式之模版方法模式

1.模版方法模式简介: a.模版方法模式的简单介绍: -  模版方法模式是编程中经常用到模式.它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现.这样,新的子类可以在不改变一个算法结构的前提上重新定义该算法的某些特定步骤. b.核心:处理某个流程中的代码已经都具备,但是其中某个节点的代码暂时不能确定.因此,我们采用模版方法模式,将这个节点的代码实现转移给子类中完成.即:处理步骤父类中定义好,具体实现延迟到子类中定义. 2.简单的代码演示: 在 BankTemplateMethod 类中添加