以下为工厂模式的详解,包括简单工厂,普通工厂模式,抽象工厂。

引子:

假设有一个交通工具公司,生产自行车,汽车,飞机等,现要销售该公司的产品,要怎么设计呢?

在交通工具商店中加一个if else判断如果是自行车就实例化(new)一个自行车,如果是汽车就实例化(new)一个汽车吗,当然不是,这样的话如果将来又加了多种交通工具那要更改每一个商店的代码,这样的话更改太多,我们应该把这部分可能变更的代码封装到另一个对象中,这个对象只管生产何种交通工具,要获得交通工具就用它。

简单工厂:

类图:

设计:

/**
* 抽像的交通工具类,里面有生产交通工具的过程方法(控制生产过程)
* @author Homg
*
*/
public abstract class Vehicle {
public abstract void produceComponent();
public abstract void assemble();
public abstract void test();
}

具体产品类,其他具体产品类(bike,plane)省略,完整代码在文章的最下方有下载地址:

/**
* 具体的产品,继承自抽象类,以用被工厂生产出来
* @author Homg
*
*/
public class Car extends Vehicle{ @Override
public void produceComponent() {
// TODO Auto-generated method stub
System.out.println("生产汽车零件");
} @Override
public void assemble() {
// TODO Auto-generated method stub
System.out.println("组装成汽车");
} @Override
public void test() {
// TODO Auto-generated method stub
System.out.println("测试汽车性能");
} }
/**
* 简单交通工具工厂,这是唯一new具体交通工具的地方
*
* @author Homg
*
*/
public class SimpleVehicleFactory {
// 该方法也可以是静态的(静态工厂)
public Vehicle createVehicle(String type) {
Vehicle vehicle = null;
if ("bike".equals(type)) {
vehicle = new Bike();
} else if ("car".equals(type)) {
vehicle = new Car();
} else if ("plane".equals(type)) {
vehicle = new Plane();
}
//可以设置默认产品以免为null
return vehicle;
}
}
/**
* 销售交通工具,工厂的使用者。
*
* @author Homg
*
*/
public class VehicleStore {
// 工厂的引用,从构造函数中获得
private SimpleVehicleFactory factory; public VehicleStore(SimpleVehicleFactory factory) {
this.factory = factory;
} // 通过传入订单的类型来获得相应的产品,不需要实例化(new)任何一个具体类,全部通过createVehicle()来获得。
public Vehicle orderVehicle(String type) {
Vehicle vehicle;
vehicle = factory.createVehicle(type);
vehicle.produceComponent();
vehicle.assemble();
vehicle.test();
return vehicle;
}
}

测试:

    public static void main(String[] args) {
SimpleVehicleFactory factory = new SimpleVehicleFactory();
VehicleStore vehicleStore = new VehicleStore(factory);
// 依次生产三种交通工具
Vehicle vehicle1 = vehicleStore.orderVehicle("car");
System.out.println("-------------------------------------");
Vehicle vehicle2 = vehicleStore.orderVehicle("bike");
System.out.println("-------------------------------------");
Vehicle vehicle3 = vehicleStore.orderVehicle("plane");
}

运行结果:
生产汽车零件
组装成汽车
测试汽车性能
-------------------------------------
生产自行车零件
组装成自行车
测试自行车性能
-------------------------------------
生产飞机零件
组装成飞机
测试飞机性能

˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙

以后如果有新的交通工具要生产,只需要更改工厂类一处即可,商店类中不需要实例化任何一个具体的交通工具类,实例化(new)操作都放到工厂类的方法中。工厂类中的创建方法也可以改成静态的(静态工厂),这样可以不用实例化对象来使用工厂方法。

简单工厂严格来说并不是真正的工厂模式,下来我们来看普通工厂模式:

现在该公司不仅要在中国销售产品,还要把产品销售到俄罗斯,也就是说,不仅要分多种产品类型,还要分不同区域生产不同风格的产品。

先看一下工厂模式的基本类图:

设计(省略部分类似代码,完整代码在文章的最下方有下载地址。):

首先要进行一些质量控制,确保分公司产品是用的总公司的流程,但不同地区的产品又需要有自己的变化,所以产品类应该这样:

/**
* 产品类,抽像的交通工具类,里面有生产交通工具的过程方法(控制生产过程),但抽象的由子具体实现
*
* @author Homg
*
*/
public abstract class Vehicle {
String name;
//各种零件
String tyre;
String engine;
String body; public void produceComponent() {
System.out.println("名字:" + name);
System.out.println("轮胎:" + tyre);
System.out.println("引擎:" + engine);
System.out.println("机身:" + body);
} public abstract void assemble(); public abstract void test();
}

子类决定具体的产品(其他具体产品类省略):

/**
* 具体的产品,继承自抽象类,根据不同地域有不同的产品
* @author Homg
*
*/
public class ChineseCar extends Vehicle{ public ChineseCar() {
name="中国汽车";
tyre="中国汽车轮胎";
engine="中国汽车引擎";
body="中国风格汽车机身";
} @Override
public void assemble() {
// TODO Auto-generated method stub
System.out.println("组装成中国风格汽车");
} @Override
public void test() {
// TODO Auto-generated method stub
System.out.println("测试俄中国格汽车性能");
} }
/**
* 具体的产品,继承自抽象类,根据不同地域有不同的产品
* @author Homg
*
*/
public class RussiaCar extends Vehicle{ public RussiaCar() {
name="俄罗斯汽车";
tyre="俄罗斯汽车轮胎";
engine="俄罗斯汽车引擎";
body="俄罗斯风格汽车机身";
} @Override
public void assemble() {
// TODO Auto-generated method stub
System.out.println("组装成俄罗斯风格汽车");
} @Override
public void test() {
// TODO Auto-generated method stub
System.out.println("测试俄罗斯风格汽车性能");
} }

工厂类需要制定一个框架,既要生产产品,不同区域又可以生产不同的产品(抽象的工厂方法):

/**
* 创建者类,定义了一个抽象的工厂方法,由子类具体实现创建什么新产品
* @author Homg
*
*/
public abstract class VehicleFactory {
//生产产品,不用管具体生产什么产品,由createVehicle方法来管
public Vehicle orderVehicle(String type) {
Vehicle vehicle;
vehicle = createVehicle(type);
vehicle.produceComponent();
vehicle.assemble();
vehicle.test();
return vehicle;
}
//抽象的创建产品方法,返回具体的产品,参数决定是什么产品。
protected abstract Vehicle createVehicle(String type);
//其他方法
}

子类工厂重写工厂方法,决定生产什么地区的产品:

/**
* 具体的工厂类,根据不同地域创建不同的产品
*
* @author Homg
*
*/
public class ChineseVehicleFactory extends VehicleFactory {
// 创建不同的产品
@Override
protected Vehicle createVehicle(String type) {
// TODO Auto-generated method stub
Vehicle vehicle = null;
if ("bike".equals(type)) {
vehicle = new ChineseBike();
} else if ("car".equals(type)) {
vehicle = new ChineseCar();
}
// 可以设置默认产品以免为null
return vehicle;
} }
/**
* 具体的工厂类,根据不同地域创建不同的产品
*
* @author Homg
*
*/
public class RussiaVehicleFactory extends VehicleFactory {
// 创建不同的产品
@Override
protected Vehicle createVehicle(String type) {
// TODO Auto-generated method stub
Vehicle vehicle = null;
if ("bike".equals(type)) {
vehicle = new RussiaBike();
} else if ("car".equals(type)) {
vehicle = new RussiaCar();
}
// 可以设置默认产品以免为null
return vehicle;
} }

测试:

    public static void main(String[] args) {
VehicleFactory chinesefactory=new ChineseVehicleFactory();
Vehicle chineseVehicle1=chinesefactory.orderVehicle("bike");
System.out.println("--------------------------------------");
Vehicle chineseVehicle2=chinesefactory.orderVehicle("car");
System.out.println("--------------------------------------");
VehicleFactory russiaFactory=new RussiaVehicleFactory();
russiaFactory.orderVehicle("bike");
System.out.println("--------------------------------------");
russiaFactory.orderVehicle("car");
}

运行结果:

名字:中国自行车
轮胎:中国自行车轮胎
引擎:生物动力
机身:中国风格自行车机身
组装成中国风格自行车
测试中国风格自行车性能
--------------------------------------
名字:中国汽车
轮胎:中国汽车轮胎
引擎:中国汽车引擎
机身:中国风格汽车机身
组装成中国风格汽车
测试俄中国格汽车性能
--------------------------------------
名字:俄罗斯自行车
轮胎:俄罗斯自行车轮胎
引擎:生物动力
机身:俄罗斯风格自行车机身
组装成俄罗斯风格自行车
测试俄罗斯风格自行车性能
--------------------------------------
名字:俄罗斯汽车
轮胎:俄罗斯汽车轮胎
引擎:俄罗斯汽车引擎
机身:俄罗斯风格汽车机身
组装成俄罗斯风格汽车
测试俄罗斯风格汽车性能

类图(产品和工厂是平行的类层级):

理解:

  工厂方法可以封装实例化的行为,封装以后可能经常变化的代码,避免代码的重复,方便以后维护。

˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙

现在来谈谈零件的生产,每次该公司要生产一批零件,用以制造某个产品,这时可以看看抽象工厂:

基本类图如下:

设计:

抽象工厂类:

/**
* 抽象工厂接口,定义了一组接口用来创建产品
* @author Homg
*
*/
public interface ComponentFactory {
public Tyre createTyre();
public Engine createEngine();
public Body createBody();
}

具体工厂类,不同地区的零件有不同的具体工厂:

/**
* 具体工厂,实现了产品家族,用户想要什么产品就用什么工厂,不需要实例化任何产品
* @author Homg
*
*/
public class ChineseComponentFactory implements ComponentFactory { @Override
public Tyre createTyre() {
// TODO Auto-generated method stub
return new ChineseTyre();
} @Override
public Engine createEngine() {
// TODO Auto-generated method stub
return new ChineseEngine();
} @Override
public Body createBody() {
// TODO Auto-generated method stub
return new ChineseBody();
} }
/**
* 具体工厂,实现了产品家族,用户想要什么产品就用什么工厂,不需要实例化任何产品
* @author Homg
*
*/
public class RussiaComponentFactory implements ComponentFactory { @Override
public Tyre createTyre() {
// TODO Auto-generated method stub
return new RussiaTyre();
} @Override
public Engine createEngine() {
// TODO Auto-generated method stub
return new RussiaEngine();
} @Override
public Body createBody() {
// TODO Auto-generated method stub
return new RussiaBody();
} }

零件家族(省略其他零件类:engine,body。完整代码在文章的最下方有下载地址):

/**
* 抽象产品
* @author Homg
*
*/
public abstract class Tyre {
String name; public String getName() {
return name;
} }
/**
* 具体产品
* @author Homg
*
*/
public class RussiaTyre extends Tyre { public RussiaTyre() {
name="俄罗斯轮胎";
} }
/**
* 具体产品
* @author Homg
*
*/
public class ChineseTyre extends Tyre { public ChineseTyre() {
name = "中国轮胎";
} }

客户类:

/**
* 客户类
* @author Homg
*
*/
public class Client {
private Tyre tyre;
private Engine engine;
private Body body;
private ComponentFactory componentFactory; public Client(String zoom) {
if ("俄罗斯".equals(zoom)) {
componentFactory = new RussiaComponentFactory();
tyre = componentFactory.createTyre();
engine = componentFactory.createEngine();
body = componentFactory.createBody();
System.out.println("生产的一批零件为:" + tyre.getName() + ","
+ engine.getName() + "," + body.getName());
} else if ("中国".equals(zoom)) {
componentFactory = new ChineseComponentFactory();
tyre = componentFactory.createTyre();
engine = componentFactory.createEngine();
body = componentFactory.createBody();
System.out.println("生产的一批零件为:" + tyre.getName() + ","
+ engine.getName() + "," + body.getName());
}
}
}

测试:

    public static void main(String[] args) {
Client client1=new Client("俄罗斯");
System.out.println("------------------------------");
Client client2=new Client("中国");
}

运行结果:
生产的一批零件为:俄罗斯轮胎,俄罗斯引擎,俄罗斯机身
------------------------------
生产的一批零件为:中国轮胎,中国引擎,中国机身

理解:

  由上面可以看出,抽象工厂是用来创建一组产品的,也就是产品家族,用户不需要关心实际生产的具体产品是什么,只需要使用相应的工厂,这样可以将用户从具体产品中解耦。

而普通工厂可以理解为是用来生产一个产品,抽象工厂用来生产产品家族。

总结:

  普通工厂模式:定义了一个创建产品对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

  抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

完整代码下载地址(也可以留下邮箱发给你):

http://download.csdn.net/detail/homg92/6919563

OO之工厂模式的更多相关文章

  1. 23种设计模式--工厂模式-Factory Pattern

    一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...

  2. 设计模式(二)简单工厂模式(Simple Factory Pattern)

    一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工厂模式. 二.简单工厂 ...

  3. .NET设计模式: 工厂模式

    .NET设计模式: 工厂模式(转) 转自:http://www.cnblogs.com/bit-sand/archive/2008/01/25/1053207.html   .NET设计模式(1): ...

  4. java 深入浅出工厂模式

    一.引子 话说十年前,有一个暴发户,他家有三辆汽车——Benz奔驰.Bmw宝马.Audi奥迪,还雇了司机为他开车.不过,暴发户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“ ...

  5. 深入浅出设计模式——抽象工厂模式(Abstract Factory)

    模式动机在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法.但是有时候我们需要一个工厂可 ...

  6. HeadFirst设计模式之工厂模式

    一. 1."工厂模式"不是种真正的设计模式,而是一种编程术语 2.The Factory Method Pattern defi nes an interface for crea ...

  7. 抽象工厂模式(Abstract Factory)

    (二)抽象工厂模式(Abstract Factory) 1.抽象工厂模式(Abstract Factory),提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 2.抽象工厂模式是 ...

  8. Head First 设计模式 第4章工厂模式

    第4章 工厂模式 在介绍工厂模式之前,先让我们来看一个例子. 这里有一个Pizza类,用来生产pizza,并返回对象,具体代码如下: package com.ek.factory.simple; im ...

  9. C#设计模式之二简单工厂模式(过渡模式)

    一.引言 之所以写这个系列,是了为了自己更好的理解设计模式,也为新手提供一些帮助,我都是用最简单的.最生活化的实例来说明.在上一篇文章中讲解了单例模式,今天就给大家讲一个比较简单的模式--简单工厂模式 ...

随机推荐

  1. 数学对象Math ceil()、floor()、round()方法

      Math.ceil()   功能:对一个数进行上取整. 语法:Math.ceil(x) 参数: x:一个数值. 返回值:返回大于或等于x,并且与之最接近的整数. 注:如果x是正数,则把小数“入”: ...

  2. How to index email and attachments in nsf files?

    My colleague she ask me why Intella could not handle Lotus Notes nsf e-mail archive files. I told he ...

  3. WinForm中使用AnyCAD三维控件 の 初始化

    在WinForm中可以方便的集成AnyCAD.Net三维控件,只需要以下几部即可完成. 一.添加DLL程序集 AnyCAD.Foundation.Net.dll AnyCAD.Presentation ...

  4. boa服务器安装

    boa是一个轻量级的web服务器,单进程单任务模式,支持CGI,是嵌入式行业应用较广的一个轻量级服务器系统. 这是我准备往嵌入式开发板里移植的时候在ubuntu上做的实验.多少有点参考价值. 现在简要 ...

  5. 缓存一致性(Cache Coherency)入门

    作者: Fabian “ryg” Giesen  来源: infoq 参考原文:http://fgiesen.wordpress.com/2014/07/07/cache-coherency/ 本文是 ...

  6. 使用css实现全兼容tooltip提示框

    在上一篇文章中,使用css实现了一个全兼容的三角形图标,这个三角型图标可以使用于多种场景,比如下拉图标.多级菜单等,这篇文章我们使用这个图标通过纯css来实现一个我们常见的tooltip提示框. 最终 ...

  7. php抓取post方式提交的页面

    function curlBy($url, $data=array()) {        $ch = curl_init();        if(!empty($data)){           ...

  8. linux 的开机启动脚本顺序

    linux 开机启动脚本顺序 linux 开机启动脚本顺序. 第一步:启动内核 第二步:执行init (配置文件/etc/inittab) 第三步:启动相应的脚本,并且打开终端/etc/init.d  ...

  9. 4.python中的用户交互

    学习完如何写'hello world'之后,我们还是不太满意,因为这样代码就写死了,以后运行的时候都只打印一局固定的话而已. 但是,我想在程序运行后,自己手动输入内容怎么办,此时就要学习如何使用用户交 ...

  10. Requests:Python HTTP Module学习笔记(一)(转)

    Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...