OO之工厂模式
以下为工厂模式的详解,包括简单工厂,普通工厂模式,抽象工厂。
引子:
假设有一个交通工具公司,生产自行车,汽车,飞机等,现要销售该公司的产品,要怎么设计呢?
在交通工具商店中加一个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之工厂模式的更多相关文章
- 23种设计模式--工厂模式-Factory Pattern
一.工厂模式的介绍 工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...
- 设计模式(二)简单工厂模式(Simple Factory Pattern)
一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工厂模式. 二.简单工厂 ...
- .NET设计模式: 工厂模式
.NET设计模式: 工厂模式(转) 转自:http://www.cnblogs.com/bit-sand/archive/2008/01/25/1053207.html .NET设计模式(1): ...
- java 深入浅出工厂模式
一.引子 话说十年前,有一个暴发户,他家有三辆汽车——Benz奔驰.Bmw宝马.Audi奥迪,还雇了司机为他开车.不过,暴发户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“ ...
- 深入浅出设计模式——抽象工厂模式(Abstract Factory)
模式动机在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法.但是有时候我们需要一个工厂可 ...
- HeadFirst设计模式之工厂模式
一. 1."工厂模式"不是种真正的设计模式,而是一种编程术语 2.The Factory Method Pattern defi nes an interface for crea ...
- 抽象工厂模式(Abstract Factory)
(二)抽象工厂模式(Abstract Factory) 1.抽象工厂模式(Abstract Factory),提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 2.抽象工厂模式是 ...
- Head First 设计模式 第4章工厂模式
第4章 工厂模式 在介绍工厂模式之前,先让我们来看一个例子. 这里有一个Pizza类,用来生产pizza,并返回对象,具体代码如下: package com.ek.factory.simple; im ...
- C#设计模式之二简单工厂模式(过渡模式)
一.引言 之所以写这个系列,是了为了自己更好的理解设计模式,也为新手提供一些帮助,我都是用最简单的.最生活化的实例来说明.在上一篇文章中讲解了单例模式,今天就给大家讲一个比较简单的模式--简单工厂模式 ...
随机推荐
- hdu2085
#include <stdio.h> int main(){ __int64 h[],l[]; int i,j; int n; ){ h[]=; l[]=; ;i<=n;++i){ ...
- 005windows与Linux文件共享
基于网络的文件共享: 前提一:从windows能够ping通Linux: 前提二:关闭Linux防火墙,命令[/etc/init.d/iptables stop]: 方法一:通过WinSCP 步骤一: ...
- java实现身份证校验
原文来自:java教程网 题目:身份证校验 身份证校验 如果让你设计个程序,用什么变量保存身份证号码呢?长整数可以吗?不可以! 因为有人的身份证最后一位是"X" 实 ...
- javascript中substring()、substr()、slice()的区别
在js字符截取函数有常用的三个slice().substring().substr()了,下面我来给大家介绍slice().substring().substr()函数在字符截取时的一些用法与区别吧. ...
- [leetcode]_Sum Root to Leaf Numbers
题目:计算一棵二叉树所有路径组成的数的总和. 思考:也是DFS的基础应用.虽然还是套着别人的DFS框架写的,但是学习通常会经历先模拟,再创新的过程. 代码: private int sum = 0; ...
- [leetcode]_Balanced Binary Tree
第四道树题,逐渐能写递归了.虽然最后AC的代码还是看了网络,但是距离成功攻克此类问题仅一步之遥. 题目:一棵树,判断是否为AVL.(AVL条件:树上任意一点的左右子树的高度差<=1) 思路:树依 ...
- C#中常见的委托(Func委托、Action委托、Predicate委托)
今天我要说的是C#中的三种委托方式:Func委托,Action委托,Predicate委托以及这三种委托的常见使用场景. Func,Action,Predicate全面解析 首先来说明Func委托,通 ...
- 多端口站点设置,以APMSERV集成环境为例!
以下以APMSERV集成环境为例: 1.找到你的apache上的配置文件httpd.conf,用记事本打开, D:\APMServ\Apache\conf 2.修改以下几项: Listen 80 下增 ...
- ASP.NET MVC4学习笔记之Controller激活的扩展
一. 为什么要进行扩展 在前面的分析中,我们知道默认的Controller激活系统只能实例化无参构造函数的Controller类型,但在某些情况一下,我们希望某些服务的实例能够自动注入到Control ...
- linux安装至少有哪两个分区,各自作用是什么?
1.至少有/代表根分区,/swap代表的意思是交换分区. 2.swap相当于缓存的作用: