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> * 工厂方法模式 * 工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽 ...
随机推荐
- (转)Geoserver基础配图研究
https://blog.csdn.net/zbcx_ZGIS/article/details/82216151 1面图层配图 1.1基本框架 这个是geoserver默认的polygon的代码,我们 ...
- Centos 6.7 安装mongodb
下载mongodb https://www.mongodb.com/download-center#community 2.解压文件 tar -zxvf mongodb-linux-x86_64-3 ...
- Linux最终将会领先于Windows、Mac OS!
Linux最终将会领先于Windows.Mac OS! 众所周知,硬件离开了软件就像人失去灵魂,而操作系统作为软件中的基础部分,更是重中之重!无论手机.电脑.还是服务器一旦离开了操作系统,比之一堆废铁 ...
- SecureCRT 使用 rz命令提示waiting to receive.**B0100000023be50
SecureCRT 远程连接Linux服务器,使用 rz命令提示waiting to receive.**B0100000023be50,或者使用sz命令提示: **B0100000023be50 解 ...
- python笔记31-使用ddt报告出现dict() -> new empty dictionary dict(mapping) 问题解决
使用ddt框架生成html报告的时候,出现:dict() -> new empty dictionary dict(mapping) -> new dictionary initializ ...
- Python:Day41 http、css
HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器和万维网服务器之间互相通信的规则. 2.请求协议 请求协议的格式如下: 请求首行: // ...
- 004_浅析Python的GIL和线程安全
在这里我们将介绍Python的GIL和线程安全,希望大家能从中理解Python里的GIL,以及GIL的前世今生. 对于Python的GIL和线程安全很多人不是很了解,通过本文,希望能让大家对Pytho ...
- 在JS中调用CS里的方法(PageMethods)
在JS中调用CS里的方法(PageMethods) 2014年04月28日 11:18:18 被动 阅读数:2998 最近一直在看别人写好的一个项目的源代码,感觉好多东西都是之前没有接触过的.今天 ...
- CF650C Table Compression
CF650C Table Compression 给一个 \(n\times m\) 的非负整数矩阵 \(a\),让你求一个 \(n\times m\) 的非负整数矩阵 \(b\),满足以下条件 若 ...
- BZOJ1023 SHOI2008 仙人掌图 仙人掌、单调队列
传送门 求仙人掌的直径,可以由求树的直径进行拓展,只需要在环上特殊判断. 沿用求树的直径的DP,对于一条不在任何环内的边,直接像树的直径一样转移,然后考虑环的影响. 设环长为\(cir\),在\(df ...