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

引子:

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

在交通工具商店中加一个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. hdu2085

    #include <stdio.h> int main(){ __int64 h[],l[]; int i,j; int n; ){ h[]=; l[]=; ;i<=n;++i){ ...

  2. 005windows与Linux文件共享

    基于网络的文件共享: 前提一:从windows能够ping通Linux: 前提二:关闭Linux防火墙,命令[/etc/init.d/iptables stop]: 方法一:通过WinSCP 步骤一: ...

  3. java实现身份证校验

    原文来自:java教程网 题目:身份证校验   身份证校验   如果让你设计个程序,用什么变量保存身份证号码呢?长整数可以吗?不可以!   因为有人的身份证最后一位是"X"   实 ...

  4. javascript中substring()、substr()、slice()的区别

    在js字符截取函数有常用的三个slice().substring().substr()了,下面我来给大家介绍slice().substring().substr()函数在字符截取时的一些用法与区别吧. ...

  5. [leetcode]_Sum Root to Leaf Numbers

    题目:计算一棵二叉树所有路径组成的数的总和. 思考:也是DFS的基础应用.虽然还是套着别人的DFS框架写的,但是学习通常会经历先模拟,再创新的过程. 代码: private int sum = 0; ...

  6. [leetcode]_Balanced Binary Tree

    第四道树题,逐渐能写递归了.虽然最后AC的代码还是看了网络,但是距离成功攻克此类问题仅一步之遥. 题目:一棵树,判断是否为AVL.(AVL条件:树上任意一点的左右子树的高度差<=1) 思路:树依 ...

  7. C#中常见的委托(Func委托、Action委托、Predicate委托)

    今天我要说的是C#中的三种委托方式:Func委托,Action委托,Predicate委托以及这三种委托的常见使用场景. Func,Action,Predicate全面解析 首先来说明Func委托,通 ...

  8. 多端口站点设置,以APMSERV集成环境为例!

    以下以APMSERV集成环境为例: 1.找到你的apache上的配置文件httpd.conf,用记事本打开, D:\APMServ\Apache\conf 2.修改以下几项: Listen 80 下增 ...

  9. ASP.NET MVC4学习笔记之Controller激活的扩展

    一. 为什么要进行扩展 在前面的分析中,我们知道默认的Controller激活系统只能实例化无参构造函数的Controller类型,但在某些情况一下,我们希望某些服务的实例能够自动注入到Control ...

  10. linux安装至少有哪两个分区,各自作用是什么?

    1.至少有/代表根分区,/swap代表的意思是交换分区. 2.swap相当于缓存的作用: