在面向对象编程中, 最通常的方法是一个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)看为工厂方法模式的一种特例,两者归为一类。

三、区别

工厂方法模式:

抽象工厂模式:

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

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

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

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

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

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

区别:

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

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

四、简单工厂模式 建立一个工厂(一个函数或一个类方法)来制造新的对象。

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

image

public class BMW320 {

public BMW320(){

System.out.println("制造-->BMW320");

}

}

public class BMW523 {

public BMW523(){

System.out.println("制造-->BMW523");

}

}

public class Customer {

public static void main(String[] args) {

BMW320 bmw320 = new BMW320();

BMW523 bmw523 = new BMW523();

}

}

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

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

image.png

产品类:

//抽象产品

abstract class BMW {

public BMW(){

}

}

//具体产品

public class BMW320 extends BMW {

public BMW320() {

System.out.println("制造-->BMW320");

}

}

//具体产品

public class BMW523 extends BMW{

public BMW523(){

System.out.println("制造-->BMW523");

}

}

工厂类:

public class Factory {

public BMW createBMW(int type) {

switch (type) {

case 320:

return new BMW320();

case 523:

return new BMW523();

default:

break;

}

return null;

}

}

客户类:

public class Customer {

public static void main(String[] args) {

Factory factory = new Factory();

BMW bmw320 = factory.createBMW(320);

BMW bmw523 = factory.createBMW(523);

}

}

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

先来看看它的组成:

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

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

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

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

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

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

五、工厂方法模式

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

工厂方法模式组成:

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

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

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

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

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

代码如下:

产品类:

//抽象产品

abstract class BMW {

public BMW(){

}

}

//具体产品

public class BMW320 extends BMW {

public BMW320() {

System.out.println("制造-->BMW320");

}

}

//具体产品

public class BMW523 extends BMW{

public BMW523(){

System.out.println("制造-->BMW523");

}

}

创建工厂类:

//现在的工厂是一个接口

interface FactoryBMW {

BMW createBMW();

}

//具体的工厂

public class FactoryBMW320 implements FactoryBMW{

@Override

public BMW320 createBMW() {

return new BMW320();

}

}

public class FactoryBMW523 implements FactoryBMW {

@Override

public BMW523 createBMW() {

return new BMW523();

}

}

客户类:

public class Customer {

public static void main(String[] args) {

FactoryBMW320 factoryBMW320 = new FactoryBMW320();

BMW320 bmw320 = factoryBMW320.createBMW();

FactoryBMW523 factoryBMW523 = new FactoryBMW523();

BMW523 bmw523 = factoryBMW523.createBMW();

}

}

总结:

这种工厂方法,如果后期还有新的具体产品,只需要继承BMW这个类(抽象产品),然后定义新的工厂,

同样是实现FactoryBMW这个接口(工厂接口),生产具体的产品就ok了。这样就符合开闭原则,对扩展开发,修改关闭。

而简单工厂方法:如果后期有新的产品,产品同样可以继承BMW这个类(抽象产品),

但是,如果要得到这个具体的产品时,需要在原来工厂类中修改代码,添加一个新产品的方法,

这样就修改了原来的代码,这就不符合开闭原则了。

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

参考:https://blog.csdn.net/jason0539/article/details/23020989

工厂模式 java_JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)相关推荐

  1. 调停者模式 java_JAVA设计模式之调停者模式详解

    在阎宏博士的<JAVA与模式>一书中开头是这样描述调停者(Mediator)模式的: 调停者模式是对象的行为模式.调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显引用.从 ...

  2. java 地图模式_Java设计模式之从[Dota地图]分析享元(Flyweight)模式

    在Dota游戏的地图中有几百棵树,现在假设这些树木无非是这两种:白杨.枫树,数量一共为400棵,那么,在装载这个地图场景的时候,我们是不是应该给这400课树一一建立对象呢?(如:MapItem tre ...

  3. 建造者模式java_java设计模式3——建造者模式

    java设计模式3--建造者模式 1.建造者模式介绍: 建造者模式属于创建型模式,他提供了一种创建对象得最佳方式 定义: 将一个复杂对象的构建和与它的表示分离,使得同样的构建过程可以创建不同的表示 主 ...

  4. 组合模式 桥接模式 java_java设计模式5.组合模式、门面模式、享元模式、桥接模式...

    组合模式 在面向对象的语言中,树结构有着巨大的威力,一个基于继承的类型的等级结构便是一个数结构,一个基于合成的对象结构也是一个数结构.组合模式将部分与整体的关系用树结构表示出来,使得客户端把一个个单独 ...

  5. 访问者模式 java_java设计模式之访问者模式

    写这篇文章之前,我也看了十几篇网络大牛写的访问者设计模式的文章,都说这个访问者模式是最复杂的一个,但是我觉得跟其他的设计模式并没有太多的不同,因此自己整理了一下,相信大多数人都能看懂. 一.认识访问者 ...

  6. 【设计模式学习】工厂方法模式

    cpp学习设计模式:工厂方法模式 在学习工厂方法模式之前,先回忆前面学的简单工厂模式: 简单工厂模式就是将对象的创建和逻辑的判断都交给了一个工厂类去做,这样做的优点是客户端不需要知道具体产品类的类名和 ...

  7. C# 设计模式-工场方法模式

    工厂方法模式简介: 工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负 ...

  8. java与模式孙悟空_悟空模式-java-工厂方法模式

    [却说那七衣仙女自受了大圣的定身法术,一周天方能解脱,各提花篮,回奏王母说道:"齐天大圣使术法困住我等,故此来迟."王母问道:"汝等摘了多少蟠桃?"仙女道:&q ...

  9. 设计模式之工厂类模式总结对比、简单工厂模式、工厂方法模式、抽象工厂模式、带反射的工厂模式、例子代码分析、最详细

    1. 题目 假设某公司同时用SqlServer.MySql数据库,即会切换两数据库(不同数据库的sql语句有些许差异),同时,两数据库里均有对Users.Departments表的操作(sql代码不一 ...

最新文章

  1. 记录如何防止跨站点脚本攻击之抄写
  2. oracle bbed 使用,Oracle BBED使用 四步快速启动Oracle BBED
  3. Vue第一部分(5):计算属性和过滤器
  4. m1 MBA配置Homebrew环境+国内源配置
  5. MySql 存储大量长字节 Text报错处理办法
  6. TIOBE 6 月编程语言排行榜:Python 势不可挡,或在四年之内超越 Java、C
  7. HTTP缓存策略 304
  8. 批量提取html文件数据库,风越批量文本提取器
  9. 『中文、英文词频统计分析软件』免费工具分享
  10. 【MATLAB】基本绘图 ( Marker 设置 | 设置 Marker 边框 | 设置 Marker 填充 )
  11. 【优雅解决】:换源后 sudo apt-get update 出现 N: Updating from such a repository can't be done securely……
  12. 捣鼓PlantUML(三、时序图)
  13. APK安装包如何安装到安卓手机上
  14. Win7安全模式卡在ClassPNP sys位置解决办法之一
  15. 镭速传输安全设计第三篇:传输安全设计
  16. 阿里年薪50WJAVA工程师转大数据学习路线!
  17. 数字通信——第一章 绪论
  18. Oracle数据库常见问题处理
  19. 杨旸:从边缘智能迈向泛在智能
  20. IE if注释判断( [if gte IE 8] )的解释网上的完全乱七八糟啊!

热门文章

  1. 01_配置管理和SaltStack概述
  2. json序列化定义类型jsckson
  3. 创建java类并实例化类对象
  4. react项目开发入门
  5. Matplotlib随记2
  6. r-cnn学习(六):RPN及AnchorTargetLayer学习
  7. ECS服务器下挂载数据盘
  8. Django常用代码基本语句
  9. 【题集】牛客网·2018年全国多校算法寒假训练营练习比赛(第二场)
  10. 线程安全和线程不安全理解