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

引子:

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

在交通工具商店中加一个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. ibatis 改下数据库连接

             <!--<dataSource name="iBatisNet" connectionString="data source= DESKTO ...

  2. SQL Server 开发指南

    SQL Server 数据库设计 一.数据库设计的必要性     二.什么是数据库设计     三.数据库设计的重要     四.数据模型          实体-关系(E-R)数据模型        ...

  3. jQuery源码的几篇文章

    http://lingyu.wang/#/post/2014/5/8/read-jq-src-1 http://lingyu.wang/#/post/2014/5/10/read-jq-src-2 h ...

  4. C#局域网桌面共享软件制作(三)

    到周末了,继续做这个桌面共享软件,下面是前两篇的链接, 链接 C#局域网桌面共享软件制作(一) 链接 C#局域网桌面共享软件制作(二) 通过对图片进行压缩以后,每张图片大小38K左右(win7/102 ...

  5. C#中string[ ] args是什么意思,又有什么用呢

    转载:http://blog.sina.com.cn/s/blog_8b7263d1010172jv.html C#控制台程序中static void Main(string[ ] args) str ...

  6. SQLite开发工具

    Sqlite 管理工具 SQLiteDeveloper及破解 功能特点 表结构设计,数据维护,ddl生成,加密数据库支持,sqlite2,3支持 唯一缺憾,收费,有试用期 下载地址: http://w ...

  7. MongoDB数据库的主从配对与迁移示例

    数据中心在运行中有可能遇到各种硬件.电力.网络故障等问题,需要设计良好的系统来隔离,尽量减少对上层应用的影响,持续对外提供服务:一旦发生业务中断,也应尽快恢复.通过主从备份设计,在主应用系统发生故障时 ...

  8. ASP.NET MVC5学习笔记之Action参数模型绑定值提供体系

    这一节我们关注模型绑定的值提供体系,先来介绍几个重要的接口 一. IValueProvider,接口定义如下: public interface IValueProvider { bool Conta ...

  9. MYSQL数据库表中字段追加字符串内容

    $sql="update parts set p_notes=concat(p_notes,'{$p_notes}') where p_id={$p_id}"; parts为表名 ...

  10. 访问svc 文件,编译器错误消息: CS0016,未能写入输出文件

    编译错误              说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息并适当地修改源代码.             编译器错误消息: CS0016: 未 ...