工厂模式分为三类:
1、简单工厂模式(simple Factory)
2、工厂方法模式(Factory Method)
3、抽象工厂模式(Abstract Factory)
一:简单工厂模式
简单工厂模式的概念
就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
简单工厂模式的UML图
简单工厂模式代码
学习简单工厂模式的时候我用的是一个与人类有相关的例子。人类在世界分为男人和女人,首先定义一个Human产品的抽象接口
/** * This is factory patter package */ package com.roc.factory; /** * 产品的抽象接口 人类 * @author liaowp * */ public interface Human { public void say(); }
然后定义男人和女人,同样都有说话的方法。
/** * This is factory patter package */ package com.roc.factory; /** * man 男人 * @author liaowp * */ public class Man implements Human { /* say method * @see com.roc.factory.Human#say() */ @Override public void say() { System.out.println("男人"); } }
/** * This is factory patter package */ package com.roc.factory; /**女人 * @author liaowp * */ public class Woman implements Human { /* say method * @see com.roc.factory.Human#say() */ @Override public void say() { System.out.println("女人"); } }
最后写一个工厂类,用来创造男人和女人。第一种方式是使用逻辑判断的方式实现的。
package com.roc.factory; /** * 简单工厂 * @author liaowp * */ public class SampleFactory { public static Human makeHuman(String type){ if(type.equals("man")){ Human man = new Man(); return man; }else if(type.equals("womman")){ Human woman = new Woman(); return woman; }else{ System.out.println("生产不出来"); return null; } } }
第二方式是使用java的放射实现的,我觉得这一类的实现方式比较好。
package com.roc.factory; /** * 简单工厂放射实现 * @author liaowp * */ public class SampleFactory1 { public static Human makeHuman(Class c){ Human human = null; try { human = (Human) Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block System.out.println("不支持抽象类或接口"); e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("没有足够权限,即不能访问私有对象"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block System.out.println("类不存在"); e.printStackTrace(); } return human; } }
最后是客户端的代码
package com.roc.factory; /** * 简单工厂测试 * @author liaowp * */ public class Client { public static void main(String[] args) { // Human man = SampleFactory.makeHuman("man"); // man.say(); // Human womman = SampleFactory.makeHuman("womman"); // womman.say(); // Human test = SampleFactory.makeHuman("tttt"); Human man = SampleFactory1.makeHuman(Man.class); man.say(); Human woman = SampleFactory1.makeHuman(Woman.class); woman.say(); } }
简单工厂模式应用场景
二:工厂方法模式
工厂方法模式的优点:
1、良好的封装性,代码结构清晰。一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。
2、工厂方法模式的扩展性非常优秀。在增加产品类的情况下,只要适当地修改具体的工厂类或者扩展一个工厂类,就可以完成“拥抱变化”。
3、屏蔽产品类。这一点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需关心产品的接口,只要接口保持不变,系统中的上层模块就不需要发生变化。因为产品类的实例化是由工厂类负责的,一个产品对象具体由哪一个产品产生是由工厂类决定的。
4、工厂方法模式是典型的解耦框架。。高层模块值需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则,我们不需要的就不要去交流;也符合依赖倒置原则,只依赖产品的抽象类;当然也符合里氏替换原则,使用产品子类替换产品父类,没问题。
工厂方法模式的通用代码如下:
1
2
3
4
5
6
7
8
9
|
//抽象产品类
public
abstract
class
Product {
//产品类的公共方法
public
void
method1() {
//业务逻辑处理
}
//抽象方法
public
abstract
void
method2();
}
|
具体的产品类可以有多个,都继承于抽象产品类,源代码如下:
1
2
3
4
5
6
7
8
9
10
11
|
//具体产品类
public
class
ConcreteProduct1
extends
Product {
public
void
method2() {
//业务逻辑处理
}
}
public
class
ConcreteProduct2
extends
Product {
public
void
method2() {
//业务逻辑处理
}
}
|
抽象工厂类负责定义产品对象的产生,源代码如下:
1
2
3
4
5
6
7
|
//抽象工厂类
public
abstract
class
Creator {
/**
*创建一个产品类,其输入参数类型可以自行设置,通常为String,Enum, Class,当然可以为空
*/
public
abstract
<T
extends
Product> T createProduct(Class<T> cls);
}
|
具体如何产生一个产品的对象,是有具体的工厂类实现的,源代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
//具体工厂类
public
class
ConcteteCreator
extends
Creator {
public
<T
extends
Product> T createProduct(Class<T> cls) {
Product product =
null
;
try
{
product = (Product)Class.forName(cls.getName()).newInstance();
}
catch
(Exception e) {
//异常处理
}
return
(T)product;
}
}
|
场景类的调用方法如下代码:
1
2
3
4
5
6
7
8
9
10
|
//场景类
public
class
Client {
public
static
void
main(String[] args) {
Creator creator =
new
ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.
class
);
/**
*继续业务处理
*/
}
}
|
改通用代码是一个比较实用、易扩展的框架,读者可以根据实际项目需要进行扩展。
希望本文所述对大家Java程序设计有所帮助。
上一篇文章(http://www.cnblogs.com/liaoweipeng/p/5768197.html)讲了简单工厂模式,但是简单工厂模式存在一定的问题,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包-开放原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
三:抽象工厂模式
抽象工厂模式的概念
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。(百度百科)
抽象工厂模式的UML图
抽象工厂模式的代码
我们接着简单工厂模式的例子继续讲解抽象工厂模式,如果在简单工厂模式中需要增加一种不男不女的人,就需要修改工厂类中的生成方法了,虽然可以实现我们需要的结果,但是违背了java的开放-闭包的原则。我们根据前面的例子做一改造。
/** * This is factory patter package */ package com.roc.factory; /** * 产品的抽象接口 人类 * @author liaowp * */ public interface Human { public void say(); }
/** * This is factory patter package */ package com.roc.factory; /**女人 * @author liaowp * */ public class Woman implements Human { /* say method * @see com.roc.factory.Human#say() */ @Override public void say() { System.out.println("女人"); } }
前面的代码是一样的,现在我们需要为一种人创建一个工厂类,既然每一个人都有自己的工厂类,那是不是可以抽一个类呢,对的,我们就抽出一个工厂接口来。
package com.roc.factory; /** * 工厂接口类 * @author liaowp * */ public interface Factory { public Human crateMan(); }创造男人的工厂类
package com.roc.factory; /** * 创造男人工厂类 * @author liaowp * */ public class ManFactory implements Factory{ public Human crateMan() { return new Man(); } }
创造女人的工厂类
package com.roc.factory; /** * 创造女人工厂类 * @author liaowp * */ public class WomanFactory implements Factory{ @Override public Human crateMan() { // TODO Auto-generated method stub return new Woman(); } }
客户端类
package com.roc.factory; /** * 抽象工厂测试 * @author liaowp * */ public class Client { public static void main(String[] args) { Factory factory=new ManFactory(); Human man2=factory.crateMan(); man2.say(); } }
改造完成,经过我这么一改造,你现在知道怎么增加创造不男不女的人吗?这样一改造你需要增加任何的类型都只需要增加一个工厂类,一个产品类。然后在客户端写出新的调用。完全符合了java的开发与闭包原则。
应用场景