工厂模式的形态


工厂模式的形态

工厂模式主要用一下几种形态:
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!

    原文作者:silenttalfrede
    原文地址: https://blog.csdn.net/silenttalfrede/article/details/52893497
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞