1.1 简单工厂(Simple Factory)模式
简单工厂模式是类的创建,又叫静态工厂方法(Static Factory Methord)模式。简单工厂模式是由一个工厂对象决定创造哪一种产品类的实例。
1.1.1 工厂模式的几种形态
工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态的决定将哪一个类实例化,工厂模式有以下几种形态:
简单工厂(Simple Factory)模式:又称静态工厂方法(Static Factory Methord)模式。
工厂方法(Factory Method)模式:又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式。
抽象工厂(Abstract Factory)模式:又称工具箱(Kit或Toolkit)模式。
下图所示的就是简单工厂模式的简略类图。
简单工厂模式,或称静态工厂方法模式,是不同工厂方法模式的一个特殊实现。在Java语言中,通常的工厂方法模式不能通过设计功能的退化给出静态工厂方法模式。
1.1.2 简单工厂模式的引进(一般模式)
比如有一个农场,生产各种水果,有苹果(Apple)、草莓(Strawberry)、葡萄(Grape);农场的园丁(FruitGardener)要根据客户的需求,提供相应的水果。下面看看是如何用简单工厂模式实现这个过程的,如下图:
此模式的实现源码如下:
1.1.2.1 产品接口-水果接口:Fruit.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:Fruit.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 0:26:51
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 抽象产品角色:工厂的水果产品接口--水果
*/
public interface Fruit {
/**
* 种植
*/
void plant();
/**
* 生长
*/
void grow();
/**
* 收获
*/
void harvest();
}
1.1.2.2 产品-平果类:Apple.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:Apple.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 0:47:25
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 水果工厂的产品:苹果
*/
public class Apple implements Fruit {
private int treeAge;
/**
* 种植
*/
public void plant() {
System.out.println("Apple has been planted.");
}
/**
* 生长
*/
public void grow() {
System.out.println("Apple is growing...");
}
/**
* 收获
*/
public void harvest() {
System.out.println("Apple has been harvested.");
}
/**
* @return 返回树龄
*/
public int getTreeAge() {
return treeAge;
}
/**
* 设置树龄
*/
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
1.1.2.3 产品-草莓类:Strawberry.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:Strawberry.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 0:45:09
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 水果工厂的产品:草莓
*/
public class Strawberry implements Fruit {
/**
* 生长
*/
public void grow() {
System.out.println("Strawberry is growing...");
}
/**
* 收获
*/
public void harvest() {
System.out.println("Strawberry has been harvested.");
}
/**
* 种植
*/
public void plant() {
System.out.println("Strawberry has been planted.");
}
/**
* 辅助方法
*/
public static void log(String msg) {
System.out.println(msg);
}
}
1.1.2.4 产品-葡萄类:Grape.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:Grape.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 0:36:56
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 水果工厂的产品:葡萄
*/
public class Grape implements Fruit {
private boolean seedless; //是否有籽
/**
* 种植
*/
public void plant() {
System.out.println("Grape has been planted.");
}
/**
* 生长
*/
public void grow() {
System.out.println("Grape is growing...");
}
/**
* 收获
*/
public void harvest() {
System.out.println("Grape has been harvested.");
}
/**
* @return 是否有籽
*/
public boolean getSeedless() {
return seedless;
}
/**
* 有无籽的赋值方法
*/
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
/**
* 辅助方法
*/
public static void log(String msg) {
System.out.println(msg);
}
}
1.1.2.5 工厂-园丁类:FruitGardener.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:FruitGardener.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 1:03:27
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 工厂类角色: 水果园丁,生产水果产品
*/
public class FruitGardener {
/**
* 静态工厂方法
* @param which :具体的产品名称
* @return 一个水果对象
* @throws BadFruitException
*/
public static Fruit factory(String which) throws BadFruitException {
if (which.equalsIgnoreCase("apple")) {
return new Apple();
} else if (which.equalsIgnoreCase("strawberry")) {
return new Strawberry();
} else if (which.equalsIgnoreCase("grape")) {
return new Grape();
} else {
throw new BadFruitException("Bad fruit request");
}
}
}
1.1.2.6 工厂异常定义类:BadFruitException.java
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:BadFruitException.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 1:04:56
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 工厂的异常处理类
*/
public class BadFruitException extends Exception {
public BadFruitException(String msg) {
super(msg); //调用父类的构造方法
}
}
1.1.2.7 一般工厂模式的测试类
package com.lavasoft.patterns.simplefactory.ybgc;
/**
* Created by IntelliJ IDEA.
* FileName:TestApp.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 1:12:08
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式模式--简单工厂模式--一般模式
* ReadMe: 一般工厂模式的测试类
*/
public class TestApp {
/**
* 测试方法
*/
private void test(String fruitName) {
try {
Fruit f = FruitGardener.factory(fruitName);
System.out.println("恭喜!生产了一个水果对象:" + fruitName);
} catch (BadFruitException e) {
System.out.println("对不起!工厂目前不能生产你所要的产品:" + fruitName);
System.out.println(e.getMessage()); //输出异常信息
e.printStackTrace(); //输出异常堆栈信息
}
}
/**
* 应用入口方法
*/
public static void main(String args[]) {
TestApp t = new TestApp();
t.test("apple");
t.test("grape");
t.test("strawberry");
t.test("car"); //此处会抛异常,水果工厂能生产car(轿车)吗!哈哈哈哈...
}
}
1.1.2.8 测试运行结果
恭喜!生产了一个水果对象:apple
恭喜!生产了一个水果对象:grape
恭喜!生产了一个水果对象:strawberry
对不起!工厂目前不能生产你所要的产品:car
Bad fruit request
com.lavasoft.patterns.simplefactory.ybgc.BadFruitException: Bad fruit request
at com.lavasoft.patterns.simplefactory.ybgc.FruitGardener.factory(FruitGardener.java:28)
at com.lavasoft.patterns.simplefactory.ybgc.TestApp.test(TestApp.java:19)
at com.lavasoft.patterns.simplefactory.ybgc.TestApp.main(TestApp.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Process finished with exit code 0
从结果看来,有异常,是因为输入了工厂不能生产的类型car(小汽车),哈哈哈哈,果园能生产汽车吗?让幼儿园的小朋友告诉你吧!
1.1.3 简单工厂模式的一般性结构
总结一下,从上面的简单工厂模式的实现可以看到,简单工厂模式需要实现
工厂角色:园丁
抽象产品:水果接口
具体产品:苹果、葡萄、草莓
另外还一般还需要实现
工厂异常类
客户类
简单工厂模式的一般性结构图如下:
1.1.4 简单工厂模式的实现
1.1.4.1 使用接口或者抽象类实现多层次的产品结构
工厂类可以有多个静态的工厂方法,分别用来生产不同的产品对象。
1.1.4.2 多个工厂方法
分别负责创建不同的产品对象,比如java.text.DateFormat类是其子类的工厂类,而DateFormat类就是提供了多个静态工厂方法。
1.1.4.3 抽象产品角色的省略
如果系统仅有一个具体产品角色产品角色的话,那么就可以省略掉抽象产品角色。省略掉抽象产品角色后的简略类图如下:
下面是一个例子,工厂角色创建具体产品,源代码如下:
1.1.4.3.1 产品角色:ConcreteProduct.java
package com.lavasoft.patterns.simplefactory.gchb;
/**
* Created by IntelliJ IDEA.
* FileName:ConcreteProduct.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 2:07:48
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
* ReadMe: 具体产品类,表示单一的一类产品.
*/
public class ConcreteProduct {
public ConcreteProduct() {
}
}
1.1.4.3.2 工厂角色:
package com.lavasoft.patterns.simplefactory.gchb;
/**
* Created by IntelliJ IDEA.
* FileName:Creator.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 1:56:43
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
* ReadMe: 具体产品类,与抽象产品角色合并,只生产单一种类产品.
*/
public class Creator {
/**
* 静态工厂方法
* @return 一个产品
*/
public static Creator factory(){
return new Creator();
}
}
1.1.4.3.3 测试类
package com.lavasoft.patterns.simplefactory.gchb;
/**
* Created by IntelliJ IDEA.
* FileName:TestApp.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 2:11:30
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
* ReadMe: 工抽合并测试类
*/
public class TestApp {
private void test() {
Creator t = Creator.factory();
System.out.println("产品成功生产!");
}
public static void main(String args[]) {
new TestApp().test();
}
}
1.1.4.3.4 测试结果
产品成功生产!
Process finished with exit code 0
1.1.4.4 工厂角色与抽象角色合并
在有些情况下,工厂角色可以由抽象产品角色扮演。典型的应用就是java.text.DateFormat类,一个抽象产品类同时是子类的工厂,如下图所示:
下面是我自己写的一个实现,源代码如下:
1.1.4.4.1 抽象产品类(同时又是工厂类)
package com.lavasoft.patterns.simplefactory.cxsl;
/**
* Created by IntelliJ IDEA.
* FileName:AbsProduct.java
* User: LavaSoft
* Date: 2006-12-3
* Time: 3:23:47
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
* ReadMe: 抽象产品类,同时又是工厂类.
*/
public abstract class AbsProduct {
static Product factory(){
return new Product();
}
}
1.1.4.4.2 具体产品类
package com.lavasoft.patterns.simplefactory.cxsl;
/**
* Created by IntelliJ IDEA.
* FileName:Product.java
* User: LavaSoft
* Date: 2006-12-3
* Time: 3:23:54
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
* ReadMe: 具体产品类
*/
public class Product {
Product(){
}
}
1.1.4.4.3 测试类
package com.lavasoft.patterns.simplefactory.cxsl;
/**
* Created by IntelliJ IDEA.
* FileName:TestApp.java
* User: LavaSoft
* Date: 2006-12-3
* Time: 3:30:30
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
* ReadMe: 测试类
*/
public class TestApp {
private void test() {
Product a = AbsProduct.factory();
System.out.println("成功创建一个产品对象!");
}
public static void main(String args[]) {
TestApp test = new TestApp();
test.test();
}
}
1.1.4.4.4 测试结果
成功创建一个产品对象!
Process finished with exit code 0
这个实现很简单,代码就不做详细解释了!
1.1.4.5 三个角色全部合并
如果在上面例子的基础上,连抽象产品角色都省略了,而工厂角色就可以与具体产品角色合并。换言之,一个产品类为自身的工厂。如下图所示:
下面给出一个简单的实现例子如下:
1.1.4.5.1 具体产品类
package com.lavasoft.patterns.simplefactory.sshb;
/**
* Created by IntelliJ IDEA.
* FileName:ConcreteProduct.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 2:20:38
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--三色合一模式
* ReadMe: 抽象产品,产品,工厂类 三和一后的具体产品类
*/
public class ConcreteProduct
{
public ConcreteProduct(){}
/**
* 静态工厂方法
* @return 具体的产品ConcreteProduct实例
*/
public static ConcreteProduct factory()
{
return new ConcreteProduct();
}
}
1.1.4.5.2 测试类
package com.lavasoft.patterns.simplefactory.sshb;
/**
* Created by IntelliJ IDEA.
* FileName:TestApp.java
* User: LavaSoft
* Date: 2006-12-1
* Time: 2:24:22
* 《Java与模式》(--阎宏博士著)读书笔记
* 工厂模式--简单工厂模式--三色合一模式
* ReadMe: 测试方法
*/
public class TestApp {
//测试方法
private void test(){
ConcreteProduct t=ConcreteProduct.factory();
System.out.println("产品成功生产!");
}
//
public static void main(String args[]){
new TestApp().test();
}
}
1.1.4.5.3 测试运行结果
产品成功生产!
Process finished with exit code 0
代码很简单,不解释了。
1.1.4.6 产品对象的循环使用和登记式的工厂方法
这里在单例模式和多例模式中在讨论。
简单工厂模式的优点和缺点
1.1.4.6.1 简单工厂模式的优点
核心式工厂类,工厂类决定在什么情况下创建哪一种产品类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅是“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
1.1.4.6.2 简单工厂模式的缺点
当产品类具有复杂的多层次等级结构时,工厂类只有它自己。以不变应万变,是其缺点。
这个工厂类集中了所有产品创建逻辑,形成了一个无所不知的全能类(也称上帝类),如果此类出问题了,整个应用都受大影响。
当产品有多个接口时,判断在什么条件下创建什么产品类实例会很困难。
对于工厂来说,增加新的产品时一个痛苦的过程。工厂角色必须知道每一种产品,如何创建它们,以及何时向客户提供它们。换言之,接纳新的产品意味着修改这个工厂角色的源代码。简单工厂只在有限的程度上支持“开-闭”原则。
由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此工厂角色无法形成基于继承的等级结构。这一缺点会在工厂方法模式中得到克服。
1.1.4.7 简单工厂模式在Java中的应用
DateFormat与简单工厂模式
SAX2库中的XMLReaderFactory与简单工厂模式
1.1.4.8 女娲捏土造人
女娲需要用土造出一个个的人,这就是简单工厂模式的应用,类图如下:
女娲是工厂角色,人是抽象产品角色,张三李四是产品。具体实现就不在给出了,参看园丁生产水果的例子。
简单工厂模式到此结束,完成时间为2006年12月3日星期日4时24分43秒。
分享到:
相关推荐
Java 设计模式圣经 喜欢的可以下载 看看
抽象工厂模式是设计模式中的一种创建型模式,它的主要目标是提供一个创建对象的接口,使得创建的对象能够独立于其实际的创建过程。这意味着客户端代码可以使用相同的接口来创建一系列相关或相互依赖的对象,而无需...
设计模式精解- GoF 23种设计模式解析附C++实现源码 懂了设计模式,你就懂了面向对象分析和...想想当时读GoF的那本圣经时候的苦闷、实现23个模式时候的探索、悟道后的欣悦,我觉得还是有这懂了设计模式,个意义。 侵删
设计模式精解-GoF23种设计模式解析附C++实现,给出了设计模式"圣经"-GOF列出的全部23种设计模式的C++实现,清晰,易懂。
java圣经,学习java的人都因该好好看这本书。
懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要。反之好像也可能成立。道可道,非常道。道不远人,设计模式亦然如此。 一直想把自己的学习经验以及在项目中的应用经历拿出来和大家共享,却总是下不了这个...
研讨课 Hands-on Java研讨课CD Thinking in Objects研讨课 Thinking in Enterprise Java Thinking in Patterns(with Java) Thinking in Patterns研讨课 设计咨询与复审 附录B 资源 软件 编辑器与IDE 书籍 分析与设计...
go语言代码大全您上传的资源如果因版权、使用、内容完整度 等原因被举报并通过官方审核,将扣除通过该资源获得的全部积分
全面深入理解C语言 C is a general-purpose programming language. It has been closely associated with the UNIX operating system where it was developed, since both the system and most of the programs that...
IO(输入/输出)是编程中不可或缺的部分,Java提供了丰富和强大的IO类库,使得文件、网络、内存以及序列化等IO操作变得简单。流(Stream)是Java中IO操作的基础,它抽象了数据传输的细节,允许开发者以一致的方法...
java代码重构以前忽视了,最近在看 字字珠玑,相见恨晚
软件研发圣经-JAVA篇,一个大师级的人物告诉你如果学好JAVA
设计模式开山之作,广大技术人员的圣经和经典,Amazon和各大书店销售榜前列,十五年来不断重印,销售逾七万册。 每次立新项目前翻一遍,绝对能给自己的头脑加上光环!程序员必备。
设计模式(Design Pattern)很重要. 不需要我多说。 你瞧 , 程序员儿子入手一本四人组( Erich Gamma. Richard Helm 、 Ralph Johnson、 John Vlissides)所著的《设计模式》。 打个比喻 : 1言耶稣的人都要读圣经...
如果说“四人帮”的《设计模式》是设计模式领域的“圣经”,那么之后出版的各种关于设计模式的书都可称之为“圣经”的“注释版”或“圣经的故事”。本书是得道者对“圣经”的“禅悟”,它既不像“圣经”那样因为惜字...
读了半辈子书就为了找个好工作。求职者必备宝典,强烈建议大家下载阅读。
- Prism的设计着重于简化复杂的IT操作,提供直观的用户界面和强大的管理功能。 **2.2 架构** - **2.2.1 Prism的服务** - Prism提供了丰富的服务,包括但不限于监控、报告、备份和恢复等功能。 - **2.3 管理导航**...
从原型批评角度看白鲸中的圣经文化原型-论文.zip
“鲸书”。鲸书侧重在对编译器后端优化的处理...在本科阶段的编译教学中旨在让学生对程序设计语言的编译全过程有系统的理解,因此会介绍编译器后端的处理技术,但不注重优化技术。鲸书更适合作为研究生的教材或参考书。