设计模式之工厂模式

工厂模式分三种:简单工厂模式(也叫静态工厂模式),工厂方法模式(也叫多形性工厂),抽象工厂模式(也叫工具箱)下面会一一举例。

一、概念

1、什么是工厂模式

这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。工厂模式关心的是最终产出(创建)的对象, 而不关心创建的过程。

2、工厂模式的优点

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。同时会给你系统带来更大的可扩展性和尽量少的修改量。(下面第三点会举例说明)

3、什么情况使用工厂模式

这也是具体的说明工厂模式优点。我个人认为在任何需要生成复杂对象的地方,都可以考虑使用工厂模式。

我们以线程池的举例。

ThreadPoolExecutor类的四个构造方法。

public class ThreadPoolExecutor extends AbstractExecutorService {
.....
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
...
}

我们可以看到线程池的构造函数要传入的参数很多参数才能创建对象,但是其实这里很多参数尤其是后面3个参数基本上用默认值,而不需每次传入。

那看下线程池的工厂模式(都是使用静态工厂模式创建对象)。

Executors.newCachedThreadPool();       //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
Executors.newSingleThreadExecutor(); //创建容量为1的缓冲池
Executors.newFixedThreadPool(int); //创建固定容量大小的缓冲池

下面是这三个静态方法的具体实现:

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

是不是都已经传入一些默认值,这让我们无需再思考在构造函数中应该传入什么值而苦恼,而直接通过工厂模式获取一个对象。

二、简单工厂模式

学习简单工厂模式的时候我用的是一个与人类有相关的例子。人类在世界分为男人和女人,首先定义一个NvWa(女娲)产品的抽象接口

/**
* 产品的抽象接口 女娲
*/
public interface NvWa { public void say();
}

然后定义男人和女人,同样都有说话的方法。

/**
* man 男人
*/
public class Man implements NvWa { @Override
public void say() {
System.out.println("男人");
} } 
/**女人
*/
public class Women implements NvWa { @Override
public void say() {
System.out.println("女人");
}
}

最后写一个工厂类,用来创造男人和女人。第一种方式是使用逻辑判断的方式实现的。

/**
* 简单工厂
*/
public class SampleFactory {
public static NvWa makeNvWa(String type){
if(type.equals("man")){
NvWa man = new Man();
return man;
}else if(type.equals("wommen")){
NvWa women = new Women();
return women;
}else{
System.out.println("生产不出来");
return null;
}
}
}

第二方式是使用java的放射实现的(推荐)

/**
* 简单工厂放射实现
*/
public class SampleFactory1 {
public static NvWa makeNvWa(Class c){
NvWa nvwa = null;
try {
nvwa= (NvWa) Class.forName(c.getName()).newInstance();
} catch (ClassNotFoundException e) {
System.out.println("类不存在");
e.printStackTrace();
}
return nvwa;
}
}

反射测试类代码

package com.roc.factory;
/**
* 简单工厂测试*/
public class Client {
public static void main(String[] args) {
NvWa man = SampleFactory1.makeNvWa(Man.class);
man.say();
NvWa women = SampleFactory1.makeNvWa(Women.class);
women.say();
}
}

总结下:

简单工厂模式实质:是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

简单工厂模式缺点:严重违反开闭原则,因为这个时候如果女王要造人妖的话,那肯定要修改工厂的方法,这就违反了开闭原则:修改关闭,对扩展开放。

三、工厂方法模式

在简单的工厂模式里,我们创建了一个类似工具的类来创建相应的具体类对象。正因为其太过简单,不符合开闭原则。

工厂方法模式就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(就是把具体抽象类多添加一层)

网上盗一张图(非常完美的图)

具体例子(把上面的具体实现工厂拆分)

NvWaFactory(造人工厂)

public abstract class NvWaFactory {
public abstract NvWacreate();
}

 Man工厂(具体工厂子类)

public class ManFactory extends NvWaFactory {
@Override
public NvWa create() {
return new Man();
}
}

WoMen工厂(具体工厂子类)

public class WomenFactory extends NvWaFactory {
@Override
public NvWa create() {
return new Women();
}
}

测试类

       /**
* 工厂方法模式:
*/
NvWaFactory factory1 = new ManFactory();
Man man= factory1.create();
man.say();

工厂方法与简单工厂的区别

可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。

工厂方法的好处就是更拥抱变化。比如现在在需要造人妖你只要在写个具体的人妖工厂,而不用像简单工厂去修改makeNvWa方法,所以工厂方法模式不会违反开闭原则。

四、抽象工厂模式

从上面的工厂方法中的结构图中,我们可以看到其中的具体工厂A和B是两个完全独立的。两者除了都是抽象工厂的子类,没有任何其他的交集。

可以理解工厂方法模式都是单产品系的。抽象工厂是多产品系 。

再盗一张图,这张图解释非常到位,下面例子如果没理解,那么再仔细思考这张图

我们修改下上面的工厂方法中的总工厂

public abstract class AbstractFactory {
/**
* 生产人类
*/
public abstract NvWa createNvWa(); /**
* 生产汽车(这个类就不具体些了,理解就好)
*/
public abstract Car createCar();
}

具体工厂1

 /*具体工厂1:这里生产男人和宝马车
*/
public class Factory1 extends AbstractFactory { @Override
public NvWa createNvWa() {
return new Man();
} @Override
public Car createCar() {
return new Bmw();
}
}

具体工厂2

 /*具体工厂2:这里生产女人和奔驰车
*/
public class Factory2 extends AbstractFactory { @Override
public NvWa createNvWa() {
return new Women();
} @Override
public Car createCar() {
return new Bc();
}
}

功能测试

有了这些东西,那么我们就来好好生产一些产品吧.

public class FactoryTest {
public static void main(String[] args) { //工厂1生产男人和宝马
AbstractFactory factory1 = new Factory1();
Man man = factory1.createNvWa();
Bmw bmw = factory1.createCar(); //工厂2生产女人和奔驰
AbstractFactory factory2 = new Factory2();
Women women = factory2.createNvWa();
Bc bc = factory2.createCar();
}
}

 个人总结下

简单工厂模式它的优点就是简单,而且违背了开闭原则。不过静态工厂模式在实际中用到比较多。工厂方法模式修复了开闭原则,但它也有一个缺点每次新增一个具体产品类,也要同时新增一个具体工厂类,会造成类太多。

工厂方法模式比抽象工厂也会用的多,因为抽象工厂结构不像工厂方法那样清晰。

想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。中校【6】

【java设计模式】(4)---工厂模式(案例解析)的更多相关文章

  1. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  2. Java设计模式之工厂模式(Factory模式)介绍(转载)

    原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...

  3. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  4. 浅析JAVA设计模式之工厂模式(二)

    1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...

  5. java设计模式2————工厂模式

    1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...

  6. java 设计模式之工厂模式与反射的结合

    工厂模式: /**  * @author Rollen-Holt 设计模式之 工厂模式  */   interface fruit{     public abstract void eat(); } ...

  7. JAVA设计模式--抽象工厂模式

    抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的 ...

  8. Java设计模式之-----工厂模式(简单工厂,抽象工厂)

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  9. Java设计模式之工厂模式(简单工厂模式+工厂方法模式)

    摘自http://blog.csdn.net/jason0539/article/details/23020989 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是 ...

  10. java设计模式之一工厂模式

    简单工厂模式是java设计模式中最简单的设计模式之一: 工厂模式是最常用的设计模式之一. 工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模 ...

随机推荐

  1. C#实现视频监控客户端onvif协议一

    前言 最近做的项目是监控方面的,需要对接各种摄像头,之前的方案是把各个厂家的SDK都集成到系统中,然后让用户进行切换,后来知道了Onvif (自行百度具体概念)这个东西.原来早就有人一统江湖了. on ...

  2. Spark内核

    一些名词概念 AM : ApplicationMaster RM : ResourceManager NM : NodeManager Backend : 后台 RpcEnv : RPC 进程和进程的 ...

  3. 决AndroidStudio 安卓模拟器安装在D盘问题

    决AndroidStudio 安卓模拟器安装在D盘问题 转 http://www.cnblogs.com/LiuDanK/articles/10106473.html 大家知道安卓的模拟器位置默认是放 ...

  4. BZOJ2143: 飞飞侠

    2143: 飞飞侠 题意: 给出两个 n ∗ m 的矩阵 A,B,以及 3 个人的坐标 在 (i, j) 支付 Ai,j 的费用可以弹射到曼哈顿距离不超过 Bi,j 的位置 问三个人汇合所需要的最小总 ...

  5. [开源] C# 封装 银海医保的接口

    Github 地址: https://github.com/zifeiniu/YinHaiYiBaoCSharpAPI C#Model封装 银海医保的接口 介绍 银海医保的接口我就不说了,很多家医院在 ...

  6. browser-sync + http-proxy-middleware 配置代理跨域

    写代理js文件下面是文件内容 /** * Module dependencies. */ var browserSync = require('browser-sync').create() var ...

  7. vue 学习小记

    vue 中有 data() .computed.methods.beforeRouteLeave.created等 具体的: data():定义一些文件中需要用到的变量,data中带return,是使 ...

  8. 导航栏动态添加act属性

    最近做了一个网站,需要设置导航栏的act属性,这里需要用到addClass以及removeClass: $('#topName li').removeClass('active'); $(this). ...

  9. node01

    ---恢复内容开始--- 1.node初体验 安装完成node,写好相应的js代码后,在cmd中node 文件名即可完成编译执行过程. 2.尝试使用node搭建一个简单服务器 //引入http模块 c ...

  10. [LeetCode] Prime Palindrome 质数回文数

    Find the smallest prime palindrome greater than or equal to N. Recall that a number is prime if it's ...