工厂设计模式(Factory)
工厂设计模式(Factory)
首先要明确,工厂模式分为三种:
- 简单工厂设计模式
- 工厂方法
- 抽象方法
一:简单工厂模式
首先来简单了解一下简单工厂模式是什么吧~
介绍:
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
好了好了,牛皮牛皮 说实话看概念我是真的一点都没看懂,什么垃圾解释,下面让我用人话重新剖析一下这句话在说什么吧~
首先我想举个例子:
好,现在我们来到了一片果园,这里漫山遍野都是果树,里面有葡萄,苹果等等等等。这里提一嘴,为什么我们需要工厂模式,首先,我们不能说想用一个小黄车,我们当场去创建这个小黄车,零件什么的都由我们自己去创造,我们需要的是一个工厂帮我们代工,我们想用的时候推出来一辆就可以了,工厂模式就是可以帮我们隐藏具体的建造细节。好了差不多就这样,我们将话题再转向这片果园~
好的,有些同学要说了:“我知道!你要抽象出来一个水果类”。
哎呀真聪明,都学会抢答了,是的,我们这里抽象一个水果类出来:
public abstract class Fruit {
abstract void grow();
abstract void harvest();
abstract void plant();
}
我觉得大家都是成年人了,不会的单词百度一下也应该知道什么意思了,这里还是帮你们标注一下吧(harvest:收获)
这里的知识很简单,用一个抽象类,把水果共有的特征抽象出来,有些同学觉得抽象的东西太抽象了,不好理解,这里的抽象,你可以理解成 抽出像的部分。比方说这里的成长,种植,收获,都是水果必经之路。
好,我们可以创建一个苹果类和葡萄类来继承这个抽象类,重写这些方法,让水果更加丰满
public class Apple extends Fruit{
@Override
void grow() {
System.out.println("苹果成长");
}
@Override
void harvest() {
System.out.println("苹果收获");
}
@Override
void plant() {
System.out.println("苹果种植");
}
}
然后这里是葡萄类:
public class Grape extends Fruit{
@Override
void grow() {
System.out.println("葡萄成长");
}
@Override
void harvest() {
System.out.println("葡萄收获");
}
@Override
void plant() {
System.out.println("葡萄种植");
}
}
好的,有些同学就要问了,工厂在哪里,别急,看下面的代码:
public class FruitFactory {
public static Fruit factory(String fruitName){
if ("apple".equals(fruitName)){
System.out.println("包装苹果");
return new Apple();
}else if ("grape".equals(fruitName)){
System.out.println("包装葡萄");
return new Grape();
}else {
return null;
}
}
}
这里我得解释一下这段代码:这是一个静态的工厂,传进来一个水果名,我们这里做一下判断,如果是苹果,我们让他包装苹果,并且返回一个新的苹果实例。葡萄也是一样的方法,直接 else if 判断一下就行(极大的加强了程序的拓展能力)。这里我们可以看到,我们丰富了建造过程,给他包装了一下。
接下来让我们看看客户端怎么操作(也就是主函数)
public class Client {
public static void main(String[] args) {
try {
Fruit grape = FruitFactory.factory("grape");
grape.plant();
}catch (Exception e){
e.printStackTrace();
}
}
}
这里我们明显的看到:我现在要一个水果,但是我们没有new这个水果,而是把工厂拿过来,直接调用方法,传参数。
好了,讲完了,是不是很简单,但是我们可以设想一下:
是不是在某些系统中,有控制台会询问你执行什么操作的话,反反复复总是那几句,所以你有没有想过,这些话不是写死在程序里面的,这个菜单可能是在外边一个文件里面,用的时候加载进来,当你需要用的时候,就像引用常量一样,把它映射过去,这样将来调用欢迎语句的时候,欢迎语句可能会改变,但是引用没有改变。这里我们就可以使用简单工厂模式的思想来考虑。
下面我把这个简单工厂模式的UML图放在下边了:
二:工厂方法
接下来要讲的工厂方法其实就是一个升级,接下来我还是举一个例子来理解工厂方法,以及为什么要使用工厂方法。
这里我们先看一张UML图,请认真看图,这里是关键,这个例子是有关苹果公司生产的产品的,众所周知,苹果公司比较出名的有iPad以及iPhone(当然还有其他的我就不举例了),我们也知道,虽然这两个产品感觉差不多,但是实际上是两个不同的产品,不管是屏幕,大小,功能都不太一样,然后你让我用同一个工厂去代工又有点别扭,所以这里我把工厂类也抽象了,就是说,你要iPad,我就给你调用iPadFactory(iPad工厂),你用iPhone,我就给你调用iPhoneFactory(iPhone工厂)。懂了吗,等于就是更具体了,更详细了。接下来我们看一下代码你就更了解了。
首当其冲的当然是创新的地方,也就是抽象的工厂类(我这里定义的是接口,一个意思),这里工厂就比较简单了,主要功能就是生产产品。
public interface Factory {
public Product factory();
}
然后就是两个加工厂了,实现Factory接口,重写生产方法(大体都差不多是相似的):
public class IpadFactory implements Factory{
@Override
public Product factory() {
return new Ipad();
}
}
public class IphoneFactory implements Factory{
@Override
public Product factory() {
return new Iphone();
}
}
还有更简单的,我定义了一个产品接口:
public interface Product {
}
是不是很简单,里面啥也没有hhh,但是这样可以提高你的一个代码复用以及拓展的能力。
接下来就是我们的两个产品了,一个是iPad,另一个是iPhone:
public class Ipad implements Product{
public Ipad(){
System.out.println("Ipad");
}
}
public class Iphone implements Product{
public Iphone(){
System.out.println("Iphone");
}
}
好了,产品定义好了,工厂也定义好了,是不是该看看主函数什么样了~
主函数:
public class Client {
public static void main(String[] args) {
Factory c1,c2;
Product p1,p2;
c1 = new IpadFactory();
p1 = c1.factory();
c2 = new IphoneFactory();
p2 = c2.factory();
}
}
这我都不用解释什么吧,都很简单,c1,c2两个产品,p1,p2两个工厂,最后各用各的工厂,代码就很明了清晰。工厂方法我就先简单介绍到这里。
三:抽象工厂
有些同学又要问了,这又是什么**玩意(自动消音),别急,听完我的介绍你会豁然开朗。
这里我还是举一个例子供大家理解,这里给大家也不说苹果了,说说男人的梦想——奔驰汽车吧,众所周知,汽车也分好多品种,比方说等级不同:A系奔驰、B系奔驰。还有产地不同:中国奔驰、德国奔驰。这里产地不同,其实可以理解成完全两个产品,比方说,中国奔驰A系,和德国奔驰A系就不一样,比方说气囊数量以及位置啊,车体钢铁硬度啊什么的都不一样(总感觉越解释越麻烦) 反正你们就当是两个商品就好了。
重点在这里,我的根本意思就是说,这里情况更加复杂了,不仅工厂抽象了,这里产品也得抽象一下,你们继续看我的代码就能理解了:
首先给大家看一下这个例子的类有哪些:
这里可以清晰的看见:
- 有抽象的奔驰A和B轿车(BenzA 和 BenzB)
- 有中国奔A和中国奔B(BenzACN 和 BenzBCN)
- 有德国奔A和德国奔B(BenzAGermany 和 BenzBGermany)
- 有奔驰工厂(MercedesFactory)
- 有中国奔驰工厂(MercedesFactoryCN)
- 有德国奔驰工厂(MercedesFactoryGermany)
- 还有主函数(Client)
接下来就是详细代码,其实你只要理解了我什么意思就行,我的意思就是想说,这里的产品也是抽象出来的,工厂方法比简单工厂模式更抽象,抽象工厂又比工厂方法抽象,一级比一级抽象,一级比一级更高级,代码灵活度越来越高,拓展能力越来越强,代码能复用的可能性越大。
接下来就是代码,我们先看抽象的车辆制造工厂这里:
public interface MercedesFactory {
public BenzA creatBenzA();
public BenzB creatBenzB();
}
然后是详细的中国工厂和德国工厂:
public class MercedesFactoryCN implements MercedesFactory{
@Override
public BenzA creatBenzA() {
System.out.println("中国生产一辆奔驰A级轿车");
return new BenzACN();
}
@Override
public BenzB creatBenzB() {
System.out.println("中国生产一辆奔驰B级轿车");
return new BenzBCN();
}
}
public class MercedesFactoryGermany implements MercedesFactory{
@Override
public BenzA creatBenzA() {
System.out.println("德国生产一辆奔驰A级轿车");
return new BenzAGermany();
}
@Override
public BenzB creatBenzB() {
System.out.println("德国生产一辆奔驰B级轿车");
return new BenzBGermany();
}
}
工厂就分这三种,让我们看看产品类:
public abstract class BenzA {
}
public abstract class BenzB {
}
两种车我就简单表示一下,大家也可以加个构造方法让车辆更加丰满。
然后看看继承产品类的中国的两款车吧:
public class BenzACN extends BenzA{
public BenzACN(){
System.out.println("中国的奔驰A");
}
}
public class BenzBCN extends BenzB{
public BenzBCN(){
System.out.println("中国的奔驰B");
}
}
然后再看看德国的两款车:
public class BenzAGermany extends BenzA{
public BenzAGermany(){
System.out.println("德国的奔驰A");
}
}
public class BenzBGermany extends BenzB{
public BenzBGermany(){
System.out.println("德国的奔驰B");
}
}
就是这么简单,我们可以通过这种方法,让代码更加整洁,所以就剩下主函数没有看了:
public class Client {
public static void main(String[] args) {
MercedesFactory factory_germany = new MercedesFactoryGermany();
BenzA a2 = factory_germany.creatBenzA();
}
}
这里主函数只要new一个工厂就可以生产轿车啦!完美!是不是很简洁!这里工厂模式就讲完啦,感觉怎么样,懂了吗我的宝贝嘻嘻嘻
好了,其实设计模式是一种思维,不是说强迫你使用这些设计模式,而是能用到就用,用不到也不所谓,只是当你有一天觉得自己的代码臃肿不堪的时候,你可以试试设计模式,会让你的代码水平提升到一个新的水平。