java 工厂模式 转载
下面介绍三种设计模式,简单工厂模式,工厂方法模式,抽象工厂模式
思考如下场景:
有一天,林同学准备去买笔记本,他到商城发现有两款电脑他特别喜欢, 一款是 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);
}
}
工厂模式的角色一般包括:
- 工厂角色: 如上图的 ComputerFactory,它可以被客户端调用,其内部用于负责创建具体的对象。
- 抽象产品类:如上图的 Computer,它描述了所有实例的公共接口。
- 具体产品类:如上图的 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 工厂模式 转载的更多相关文章
- java工厂模式
(1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...
- Java工厂模式解耦 —— 理解Spring IOC
Java工厂模式解耦 -- 理解Spring IOC 最近看到一个很好的思想来理解Spring IOC,故记录下来. 资源获取方式 主动式:(要什么资源都自己创建) 被动式:(资源的获取不是我们创建, ...
- Java学习笔记——Java工厂模式之简单工厂
package com.app; import java.util.Date; /* * 工厂模式:简单工厂.工厂方法.抽象工厂 * * */ public class Test0718_Factor ...
- JAVA - 工厂模式
1. 简单工厂违背OCP(Open Close Principle)原则 , 即对增加开放,对修改关闭.如果要符合OCP原则,要针对接口编程. //简单工厂模式,违反了OCP原则 public cla ...
- Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式
一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...
- Java 工厂模式(一)— 简单工厂模式
一.什么是工厂模式: Java中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...
- java工厂模式个人体会
上一边文章主要对单例模式做了一个总结,这篇文章主要对工厂模式也写一写个人的体会. 工厂模式是设计模式的一种,它主要是把实现产品对象的过程封装起来,然后提供给客户端相应的接口.工厂模式也是有3种,分别为 ...
- 自己理解的java工厂模式,希望对大家有所帮助
[http://www.360doc.com/content/11/0824/17/3034429_142983837.shtml] 这两天突然想学学java源代码,不过看到一篇文章说看java源代码 ...
- java工厂模式的测试
/** * 工厂模式的测试 * <p> * 工厂方法模式 * 工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽 ...
随机推荐
- J - Abbott's Revenge 搜索 寒假训练
题目 题目大意:这个题目就是大小不超过9*9的迷宫,给你起点终点和起点的方向,让你进行移动移动特别之处是不一定上下左右都可以,只有根据方向确定可以走的方向.思路:需要写一个读入函数,这个需要读入起点, ...
- 【NOI2008】志愿者招募
[NOI2008]志愿者招募 和[2017山东day7]养猫做法类似. 都是神仙题. 首先我设\(c_{i,j}=[l[j]\leq i\leq r[j]]\) ,于是就可以列出下面的不等式: \[ ...
- 定时器 setTimeout()超时调用和 setInterval()间歇调用
JavaScript是单线程语言,但它允许通过设置定时器,也就是设置超时值和间歇时间来调度代码在特定的时刻执行.前者是在指定的时间过后执行代码,而后者则是每隔指定的时间就执行一次代码. 超时调用需要使 ...
- [1] YOLO 图像检测 及训练
YOLO(You only look once)是流行的目标检测模型之一, 原版 Darknet 使用纯 C 编写,不需要安装额外的依赖包,直接编译即可. CPU环境搭建 (ubuntu 18.04) ...
- 微信小程序如何引入外部字体库iconfont的图标
每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code 微信小程序不能识别很多文件, 其中就包括外部的字体文件. 那我们怎么突破他的防火线呢, ...
- Docker安装MySQL并配置远程访问
1.docker search mysql 查看mysql版本 2.docker pull mysql 要选择starts最高的那个name 进行下载 3.docker images 查看下载好的镜像 ...
- 线程的synchronized、volatile及原子操作
public class ThreadDemo7{ //structs2线程不安全 共享变量 //n++ 复合操作 对于volatile修饰的变量不安全 //原子操作 int value; //让方法 ...
- 从code review到Git commit log
最近在读一本技术类的书:朱赟——<跃迁:从技术到管理的硅谷路径>,其中聊了很多很有趣的观点,比如:技术管理.技术实践.硅谷文化.个人成长等. 读到关于硅谷人如何做code review这一 ...
- 洛谷 P1451 求细胞数量
题目链接 https://www.luogu.org/problemnew/show/P1451 题目描述 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字 ...
- UVA - 10931-Parity
题意:1.输入一个数,将其转换为二进制.2.记录二进制中出现1的次数. 注意:转换二进制后直接输出,不能转换为十进制后输出 #include<iostream> #include<c ...