下面介绍三种设计模式,简单工厂模式,工厂方法模式,抽象工厂模式

思考如下场景:

有一天,林同学准备去买笔记本,他到商城发现有两款电脑他特别喜欢, 一款是 Macbook Pro, 另一款是 Surface Pro。

根据以上的场景,类图可以如下表示:

interface Computer {
public void printComputer();
} class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a macbook pro");
}
} class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a surface book");
}
} public class Client {
public void buy(Computer c){
c.printComputer();
}
public static void main(String[] args) {
Client c = new Client();
c.buy(new SurfaceBookComputer());
}
}

这时候问题就来了,客户只关心得到电脑,并不关心电脑是如何被生产出来的,假设这里电脑是由鼠标,键盘和显示器组成,那么我们还需要先创建这些类实例,才能创建电脑。

Keyboard keyboard = new Keyboard();
Display display = new Display();
Mouse mouse = new Mouse();
Client c = new Client();
c.buy(new SurfaceBookComputer(keyboard, display, mouse));

显然商家在卖电脑的时候不会要求客户自己把电脑组装好的吧。

简单工厂模式

下面就先介绍简单工厂模式。

简单工厂模式:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。

这里我们相当于是创建生产电脑的工厂,客户需要购买什么样的电脑,只要输入类型编号就可以获取该电脑,而无需知道该电脑是如何被生产出来的。

类图如下表示:

Java 代码:

interface Computer {
public void printComputer();
} class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a macbook pro");
}
} class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a surface book");
}
} class ComputerFactory {
public Computer createComputer(String type) {
Computer c = null;
if(type.equals("macbook")) {
c = new MacbookProComputer();
}else if(type.equals("surface")) {
c = new SurfaceBookComputer();
}
return c;
}
} public class Client {
public void buy(Computer c){
System.out.println("I buy a computer");
c.printComputer();
}
public static void main(String[] args) { Client c = new Client();
ComputerFactory cf = new ComputerFactory(); Computer computer = cf.createComputer("macbook");
c.buy(computer);
}
}

工厂模式的角色一般包括:

  1. 工厂角色: 如上图的 ComputerFactory,它可以被客户端调用,其内部用于负责创建具体的对象。
  2. 抽象产品类:如上图的 Computer,它描述了所有实例的公共接口。
  3. 具体产品类:如上图的 MacbookProComputer,实现抽象产品的接口,是工厂角色中要创建的具体实例。

简单工厂模式的优点从上面两种方式对比可以看出,工厂角色负责产生具体的实例对象,所以在工厂类中需要有必要的逻辑,通过客户的输入能够得到具体创建的实例;所以客户端就不需要感知具体对象是如何产生的,只需要将必要的信息提供给工厂即可。

这时候负责这个工厂的产品经理说该工厂需要生产新的产品 Macbook Air, 那么该方法的缺点就暴露显现,一般工厂生产方法和具体产品实现一般是由不同工程师开发的,那么如果实现产品的工程师早早实现了新产品而工厂方法却一直没有更新,那么该产品就一直无法上架。其次代码耦合度太高,如果工厂方法由新来的工程师去修改的话,那么他又得先读懂源代码,效率显得低下。

所以简单工厂模式的缺点:简单工厂模式是违反“开闭原则”,即对扩展开放,对修改关闭;因为如果要新增具体产品,就需要修改工厂类的代码。

针对简单工厂模式暴露出来的弊端,我们需要对代码再进行改进,由此延伸出工厂方法模式。

工厂方法模式

工厂方法模式:定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类。

工厂方法模式是针对每个产品提供一个工厂类,在客户端中判断使用哪个工厂类去创建对象。

我们将之前的 ComputerFactory 抽象成一个接口,那么创建相应具体的工厂类去实现该接口的方法。

具体类图的实现:

Java 代码实现:

interface Computer {
public void printComputer();
} class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a macbook pro");
}
} class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a surface book");
}
}
interface ComputerFactory {
public Computer createComputer();
} class MsFactory implements ComputerFactory {
public Computer createComputer(){
return new SurfaceBookComputer();
}
} class AppleFactory implements ComputerFactory {
public Computer createComputer() {
return new MacbookProComputer();
}
} public class Client {
public void buy(Computer c){
System.out.println("I buy a computer");
c.printComputer();
}
public static void main(String[] args) { Client c = new Client();
ComputerFactory cf = new AppleFactory(); Computer computer = cf.createComputer();
c.buy(computer);
}
}

工厂方法模式是针对每个产品提供一个工厂类,在客户端中判断使用哪个工厂类去创建对象。

对比简单工厂模式和工厂方法模式:

对于简单工厂模式而言,创建对象的逻辑判断放在了工厂类中,客户不感知具体的类,但是其违背了开闭原则,如果要增加新的具体类,就必须修改工厂类。

对于工厂方法模式而言,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的工厂类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。

工厂模式横向扩展很方便,假如该工厂又有新的产品 Macbook Air 要生产,那么只需要创建相应的工厂类和产品类去实现抽象工厂接口和抽象产品接口即可,而不用去修改原有已经存在的代码。

抽象工厂模式:

这时候负责该工厂的产品经理说要生产新的一类产品操作系统 Mac Os 和 Windows 8,这时候就引申出了抽象工厂模式。

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

工厂方法模式和抽象工厂模式基本类似,可以这么理解:当工厂只生产一个产品的时候,即为工厂方法模式,而工厂如果生产两个或以上的商品即变为抽象工厂模式。

我们在抽象工厂接口中新增创建系统的方法,并由实例工厂类去实现。

类图可由下表示:

interface Computer {
public void printComputer();
} class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a macbook pro");
}
} class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a surface book");
}
} interface OperatingSystem {
public void printSystem();
} class MacOsSystem implements OperatingSystem {
public void printSystem() {
System.out.println("This is a mac os");
}
} class Windows8System implements OperatingSystem {
public void printSystem() {
System.out.println("This is a window 8");
}
} interface ProductionFactory {
public Computer createComputer();
public OperatingSystem createSystem();
} class AppleFactory implements ProductionFactory {
public Computer createComputer() {
return new MacbookProComputer();
}
public OperatingSystem createSystem() {
return new MacOsSystem();
}
} class MsFactory implements ProductionFactory {
public Computer createComputer() {
return new SurfaceBookComputer();
}
public OperatingSystem createSystem() {
return new Windows8System();
}
} public class Client { public void buy(Computer c){
System.out.println("I buy a computer");
c.printComputer();
}
public void use(OperatingSystem s) {
System.out.println("Operating System");
s.printSystem();
}
public static void main(String[] args) { ProductionFactory pf = new AppleFactory();
Computer c = pf.createComputer();
OperatingSystem s = pf.createSystem(); Client client = new Client();
client.buy(c);
client.use(s); }
}

抽象工厂模式的缺点在于产品类的扩展,将会是十分费力的,假如在需要加入新的产品,那么几乎所有的工厂类都需要进行修改,所以在使用抽象工厂模式时,对产品等级结构的划分是十分重要的。

适用场景:

无论是简单工厂模式,工厂方法模式还是抽象工厂模式,它们都具有类似的特性,适用场景也十分类似。

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

所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的产品,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。

java 工厂模式 转载的更多相关文章

  1. java工厂模式

    (1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...

  2. Java工厂模式解耦 —— 理解Spring IOC

    Java工厂模式解耦 -- 理解Spring IOC 最近看到一个很好的思想来理解Spring IOC,故记录下来. 资源获取方式 主动式:(要什么资源都自己创建) 被动式:(资源的获取不是我们创建, ...

  3. Java学习笔记——Java工厂模式之简单工厂

    package com.app; import java.util.Date; /* * 工厂模式:简单工厂.工厂方法.抽象工厂 * * */ public class Test0718_Factor ...

  4. JAVA - 工厂模式

    1. 简单工厂违背OCP(Open Close Principle)原则 , 即对增加开放,对修改关闭.如果要符合OCP原则,要针对接口编程. //简单工厂模式,违反了OCP原则 public cla ...

  5. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  6. Java 工厂模式(一)— 简单工厂模式

    一.什么是工厂模式: Java中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...

  7. java工厂模式个人体会

    上一边文章主要对单例模式做了一个总结,这篇文章主要对工厂模式也写一写个人的体会. 工厂模式是设计模式的一种,它主要是把实现产品对象的过程封装起来,然后提供给客户端相应的接口.工厂模式也是有3种,分别为 ...

  8. 自己理解的java工厂模式,希望对大家有所帮助

    [http://www.360doc.com/content/11/0824/17/3034429_142983837.shtml] 这两天突然想学学java源代码,不过看到一篇文章说看java源代码 ...

  9. java工厂模式的测试

    /** * 工厂模式的测试 * <p> * 工厂方法模式 * 工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽 ...

随机推荐

  1. 《生命》第一集:Chanllenge of Life (生命的挑战)

    开篇讲的是弗罗里达海岸的海豚用尾巴荡起浑水圈批量捕鱼,肯尼亚的猎豹用集体战术捕猎体积大于自己的鸵鸟,马达加斯加的变色龙用伪装的方式来偷袭昆虫,紧接着讲的是南极洲的食蟹海豹如何从天敌虎鲸的围捕中惊险逃脱 ...

  2. 【PS技巧】如何拼图

    1.材料准备 根据对图片的内容表达,粗略的“计划”,每张图片摆放位置及尺寸.C与D等高,C/D与B叠高后与A等高.C与D叠宽后与B等宽. 2.记录每张图片原始大小 (1)双击工作区,打开待拼接图片 ( ...

  3. SQL INNER JOIN 关键字

    SQL INNER JOIN 关键字 在表中存在至少一个匹配时,INNER JOIN 关键字返回行. INNER JOIN 关键字语法 SELECT column_name(s) FROM table ...

  4. 磁盘性能评价指标—IOPS和吞吐量

    转:http://blog.csdn.net/hanchengxi/article/details/19089589 一.磁盘 I/O 的概念 I/O 的概念,从字义来理解就是输入输出.操作系统从上层 ...

  5. 003_webpack 配合babel 将es6转成es5

    今天接触了webpack,第一次使用webpack进行转码,竟然稀里糊涂就成功了,哈哈. 下面附上流程 创建个文件夹,初始化一下,首先全局安装webpack npm install webpack - ...

  6. 七、Oracle 数据库设计

    1. 原始单据与实体之间的关系 可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体. 在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证 ...

  7. Spring MVC Content Negotiation 转载

    Spring MVC Content Negotiation 2017年11月15日 00:21:21 carl-zhao 阅读数:2983   Spring MVC有两种方式生成output的方法: ...

  8. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  9. face detection[FaceBoxes]

    该文来自<FaceBoxes: A CPU Real-time Face Detector with High Accuracy>.该文时间线是2018年1月 虽然人脸检测上随着深度学习的 ...

  10. .NetCore实践爬虫系统(一)解析网页内容

    爬虫系统的意义 爬虫的意义在于采集大批量数据,然后基于此进行加工/分析,做更有意义的事情.谷歌,百度,今日头条,天眼查都离不开爬虫. 今日目标 今天我们来实践一个最简单的爬虫系统.根据Url来识别网页 ...