工厂模式主要用一下几种形态:
1:简单工厂(Simple Factory)。
2:工厂方法(Factory Method)。
3:抽象工厂(Abstract Factory)。
简单工厂(Simple Factory)
又叫静态工厂,是工厂模式三中状态中结构最为简单的。 有一个静态方法,用来接受参数,根据参数决定返回实现同一接口的不同类的实例。我们来看一个演唱会工厂具体的例子:
假设一场演唱会,根据观众要求,会请来明星:刘德华,张学友,陈奕迅. . . . . .(为什么没有女的?)
我们先为所有明星们定义一个接口
package 简单工厂;
public interface Star {
}
package 简单工厂;
public class 刘德华 implements Star {
public 刘德华() {
System.out.println("刘德华在唱歌");
}
}
class 陈奕迅 implements Star {
public 陈奕迅() {
System.out.println("陈奕迅在唱歌");
}
}
class 张学友 implements Star {
public 张学友() {
System.out.println("张学友在唱歌");
}
}
接下来我们来写一个演唱会的类,(方法名不是factory了,感觉怪怪的)由它来负责邀请明星
package 简单工厂;
public class Concert {
public static Star 个人专场(String starName) throws Exception {
if (starName.equals("刘德华")) {
return new 刘德华();
}
else if (starName.equals("张学友")) {
return new 张学友();
}
else if (starName.equals("陈奕迅")) {
return new 陈奕迅();
}
else {
throw new Exception("没有该明星");
}
}
}
好了,有了这个演唱会类,我们就可以喊话了,Concert将根据不同的名字来决定哪个明星(顺带复习finally)。
好了,演唱会上半场:
package 简单工厂;
public class Test {
public static void main(String[] args) {
System.out.println("是谁在唱歌?");
try {
Concert.个人专场("刘德华");
Concert.个人专场("张学友");
Concert.个人专场("陈奕迅");
} catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("温暖了寂寞");
}
}
}
可以看出,简单工厂的核心就是一个Concert类,他拥有判断能力和创建对象的控制权,我们只需要向他喊话,就能得到我们想要的明星,是不是很爽?实际上,这个Concert有很多的局限。
1、我们每次想要增加一个新明星的时候,都必须修改Concert的原代码,例如叫上杨千嬅。
if (starName.equals("杨千嬅")) {
return new 杨千嬅();
}
2、当我们拥有很多很多明星的时候,而且明星之间又有复杂的附属关系的时候(例如团队:凤凰传奇),这个类必须拥有复杂的逻辑判断能力,其代码量也将不断地增加,邀请就麻烦了,那演出就开不成了?
3、整个系统都严重依赖Concert类,只要Concert类一出问题,
德华和学友就唱不成了啊!
德华和学友就唱不成了啊!
德华和学友就唱不成了啊!
这也是最为致命的一点....
那怎么可以?于是,工厂模式带你嗨翻天. . . . . . .
工厂方法(Factory Method)
工厂方法为演唱会类定义了接口,用多态来削弱了演唱会类的职能,以下是工厂接口的定义:
package 工厂方法;
public interface Concert {
public Star 个人专场();
}
package 工厂方法;
public interface Star {
}
下面是实现了明星接口的明星类
package 工厂方法;
public class 刘德华 implements Star {
public 刘德华() {
System.out.println("刘德华在唱歌");
}
}
class 陈奕迅 implements Star {
public 陈奕迅() {
System.out.println("陈奕迅在唱歌");
}
}
class 张学友 implements Star {
public 张学友() {
System.out.println("张学友在唱歌");
}
}
接下来,就是工厂方法的核心部分,也就是具体创建明星对象的具体演唱会类
<pre name="code" class="html">package 工厂方法;
public class Concert刘德华 implements Concert {
public Star 个人专场() {
return new 刘德华();
}
}
//创建张学友演唱会的工厂
class Concert张学友 implements Concert {
public Star 个人专场() {
return new 张学友();
}
}
//创建陈奕迅演唱会的工厂
class Concert陈奕迅 implements Concert {
public Star 个人专场() {
return new 陈奕迅();
}
}
演唱会下半场
package 工厂方法;
public class Test {
public static void main(String[] args) {
System.out.println("是谁在唱歌?");
try {
Concert 刘德华 = new Concert刘德华();
刘德华.个人专场();
Concert 张学友 = new Concert张学友();
张学友.个人专场();
Concert 陈奕迅 = new Concert陈奕迅();
陈奕迅.个人专场();
} catch (Exception e) {
e.printStackTrace();
}
}
}
从上面创建明星对象的代码可以看出,工厂方法和简单工厂的主要区别是:
简单工厂把创建明星的职能都放在一个演唱会类,工厂方法把不同的明星放在实现了工厂接口的不同演唱会类,这样就算其中一个演唱会类出了问题,其他演唱会类也能正常工作,互相不受影响,以后增加新明星,也只需要新增一个新的明星演唱会的工厂类,就可以了,不用修改已有的代码。
工厂方法也有他局限的地方,那就是当面对的全能或半能的明星时,就像舞王、歌王、歌舞王,你总不能叫刘欢去跳舞吧,所以,你的演唱会就要分门别类了,简单点~~~,唱歌中间,跳舞右边,歌舞中间(阿三,你走哪里,中间别动!)当这些情况交织时,就形成了一个复杂的明星树了。
如果用工厂方法来设计这个明星家族系统,就必须为每种明星创建一个对应的演唱会类,当有数百种甚至上千种明星的时候,也必须要有对应的上百成千个演唱会类,这就出现了传说的类爆炸,简直就是一场灾难,那还开不开?开!!!!!
抽象工厂(Factory Method)
抽象工厂:意的意图在于创建一系列互相关联或互相依赖的对象。<<Java设计模式>>
抽象工厂是在工厂方法的基础上引进了分类管理的概念(这个很重要). . . . .
工厂方法用来创建一个明星,它没有分类的概念,而抽象工厂则用于创建一系列明星,所以明星分类成了抽象工厂的重点。
刚才你们听的嗨不嗨,那就来个不散场吧!!!!
明星嘛,歌王(张学友),舞王(郭富城),歌舞王(王迈克杰克逊),这就是对应明星的种类,所有明星都会加入不同的club,就形成了明星树
首先,进行分类:
刘德华:唱歌的刘德华跳舞的刘德华张学友:唱歌的张学友跳舞的张学友陈奕迅:唱歌的陈奕迅跳舞的陈奕迅
我们可以为明星们分别定义两个明星接口,以对他们进行分类
package 抽象工厂;
public interface 刘德华 {
}
interface 陈奕迅 {
}
interface 张学友 {
}
接着,我们来实现接口
package 抽象工厂;
public class 唱歌的刘德华 implements 刘德华 {
public 唱歌的刘德华() {
System.out.println("唱歌的刘德华");
}
}
class 跳舞的刘德华 implements 刘德华 {
public 跳舞的刘德华() {
System.out.println("跳舞的刘德华");
}
}
class 唱歌的陈奕迅 implements 陈奕迅 {
public 唱歌的陈奕迅() {
System.out.println("唱歌的陈奕迅");
}
}
//陈奕迅跳舞不行啊,不管了
class 跳舞的陈奕迅 implements 陈奕迅 {
public 跳舞的陈奕迅() {
System.out.println("跳舞的陈奕迅");
}
}
class 唱歌的张学友 implements 张学友 {
public 唱歌的张学友() {
System.out.println("唱歌的张学友");
}
}
class 跳舞的张学友 implements 张学友 {
public 跳舞的张学友() {
System.out.println("跳舞的张学友");
}
}
到此,明星部分我们准备好了,接下来我们来处理演唱会部分,我们先来定义接口
package 抽象工厂;
public interface Concert {
public 刘德华 create刘德华();
public 张学友 create张学友();
public 陈奕迅 create陈奕迅();
}
接下来我创造具体的演唱会类,我们根据上面明星的接口,把唱歌的明星分为一类,由一个演唱会来管理,把跳舞的明星有另一个演唱会管理,根据这个分类,我们可以实现如下的两个具体演唱会类
package 抽象工厂;
//创建唱歌的演唱会
public class 演唱会 implements Concert {
public 刘德华 create刘德华() {
return new 唱歌的刘德华();
}
public 张学友 create张学友() {
return new 唱歌的张学友();
}
public 陈奕迅 create陈奕迅() {
return new 唱歌的陈奕迅();
}
}
//创建跳舞的演唱会(演跳会)
class 演跳会 implements Concert {
public 刘德华 create刘德华() {
return new 跳舞的刘德华();
}
public 张学友 create张学友() {
return new 跳舞的张学友();
}
public 陈奕迅 create陈奕迅() {
return new 跳舞的陈奕迅();
}
}
这样,我们的抽象工厂就完成了。Music!
package 抽象工厂;
public class Test {
public static void main(String[] args) {
Concert 唱歌 = new 演唱会();
刘德华 刘德华唱歌 = 唱歌.create刘德华();
张学友 张学友唱歌 = 唱歌.create张学友();
陈奕迅 陈奕迅唱歌 = 唱歌.create陈奕迅();
Concert 跳舞 = new 演跳会();
刘德华 刘德华跳舞 = 跳舞.create刘德华();
张学友 张学友跳舞 = 跳舞.create张学友();
陈奕迅 陈奕迅跳舞 = 跳舞.create陈奕迅();
}
}
散场别忘了点个赞o!