关于工厂模式的一些理解

简介:这篇文章的重点呢,不在于如何编写工厂模式的Java代码,而在于"为什么要使用工厂模式"。

有这样一个场景👇

首先有这样一个接口:果汁接口——Juice,该接口只有一个方法,就是被饮用——void drink();。现在有2个品牌的果汁,自然,他们都实现了该接口,这两个类分别就是
光明牌果汁——BrightJuice 以及
暗夜牌果汁——DarkJuice
那么我们想要喝果汁,肯定是生产出其中一个对象,比如说:

Juice bJuice = new BrightJuice();// 创建一杯光明果汁对象
bJuice.drink();// 喝光明果汁
--------------------------------------------------------
Juice dJuice = new DarkJuice();// 创建一杯暗夜果汁对象
bJuice.drink();// 喝暗夜果汁

但是,果汁的制作并不是这么简单,一杯果汁的诞生,还需要果汁师,水果原料,糖浆,水,色素,秘制配方等。所以,我们创建一杯果汁,就会变成这个样子。

Juice bJuice = new BrightJuice("果汁师Tony","左边第2个桃子","糖浆20g","100ml水","红色色素","秘制配方1");
bJuice.drink();// 喝光明果汁
-----------------------------------------------------------------------------------------------------
Juice dJuice = new DarkJuice("果汁师Jerry","左边第4个菠萝","糖浆30g","100ml水","蓝色色素","秘制配方2");
bJuice.drink();// 喝暗夜果汁

没错,参数很多。而现实世界往往就是这么复杂,也许真的做出一杯果汁,是需要十余种参数的。那么对想要喝果汁的人来说,就很不友好了——创建一杯果汁所要做的事情太多了。于是,为了让果汁的创建和使用(被喝)分离,也为了每次创建果汁时的复杂传参代码可以得到复用,我们需要使用一些技巧,来改进代码的结构。

简单工厂(静态工厂)

没错,就是使用简单工厂。因为new出果汁对象的操作过于繁琐,所以我们专门写一个类,让这个类帮我们去新建果汁对象,而这个类,我们就称它为——果汁工厂——JuiceFactory。这个类只有一个方法,也就是说他只干一件事情——就是生产果汁对象。这个方法我们取名为Juice createJuice(String brand);
通过该参数命名我们可以看出来,因为有2种牌子的果汁可以生产,所以我们在要求它生产的时候,需要去指定究竟是哪一种:

public class JuiceFactory {
    static public Juice createJuice(String brand) {
        if(brand == null){
            return null;
        }
        if(brand.equalsIgnoreCase("bright")){
            return new BrightJuice("果汁师Tony","左边第2个桃子","糖浆20g","100ml水","红色色素","秘制配方1");
        } else if(brand.equalsIgnoreCase("dark")){
            return new DarkJuice("果汁师Jerry","左边第4个菠萝","糖浆30g","100ml水","蓝色色素","秘制配方2");
        } else {
            return null;
        }
    }
}

可以看出,我们使用这种方式,当我们想喝果汁时候,只需要这样:

Juice bJuice = JuiceFactory.createJuice("bright");
bJuice.drink();// 喝光明果汁
-----------------------------------------------------------------------------------------------------
Juice bJuice = JuiceFactory.createJuice("dark");
bJuice.drink();// 喝暗夜果汁

代码又变成了简单的模样。,就是简单工厂的魅力。但是,假如现在又来了一个品牌——黎明牌果汁。那么很明显,我们需要在JuiceFactory类的createJuice方法里再添加一个黎明牌的else if语句。也就是说,我们在添加新的类时,要去修改原来写好的类,这种行为是很不"面向对象"的,也是很不方便的。所以,我们还要对代码进行改进。

工厂

我果汁工厂——JuiceFactory,之所以会随着新品牌的添加而修改,就是因为还不够抽象。那么我就抽象成一个接口——也就是说,我虽然还是会提供一个创建果汁——createJuice的方法,但我不自己去生产了,你们谁想要生产,就来实现我这个接口。这样一来,光明牌喝暗夜牌就分家了,各自建立了工厂 (而不是以前只有一家果汁工厂的方式)。也就是如下的方式:
BrightJuiceFactory implements JuiceFactory
DarkJuiceFactory implements JuiceFactory
LiMingJuiceFactory implements JuiceFactory//黎明牌果汁工厂
当然,他们各自实现的JuiceFactory接口createJuice方法,自然就是创建各自家品牌的果汁对象。如光明工厂:

public class BrightJuiceFactory implements JuiceFactory, {
    @Override
    public void createJuice() {
		return new BrightJuice("果汁师Tony","左边第2个桃子","糖浆20g","100ml水","红色色素","秘制配方1");
    }
}

这样,我们喝果汁的方式就变成了:

Juice bJuice = BrightJuiceFactory实例.createJuice();
bJuice.drink();// 喝光明果汁
-----------------------------------------------------------------------------------------------------
Juice bJuice = DarkJuiceFactory实例.createJuice();
bJuice.drink();// 喝暗夜果汁

实现了对象创建和使用的分离,而且依然得简单明了。同时还解决了新品牌加入时扩展性的问题。顺便一提:简单工厂是使用字符串传参的方式来决定创建哪一个子类对象,这就暗藏着不小心拼错单词的可能,从而得到空的对象,而工厂方法,也很大程度上避免了该隐患的发生(毕竟写出了不存在的工厂类会编译报错的)。
这种结构的搭建,主要解决的问题是——当厂家增多的时候(比如:多了黎明牌这一公司),如何减少代码量的修改以及保证代码的秩序性(不是专业名词,自己想的描述词,就是让代码看起来是有逻辑的)。
但是,某天,时代变了,社会开始流行一款下午茶组合——一份果汁🍹+小蛋糕🎂。光明公司和暗夜公司为了抢占市场,也立即推出了光明牌蛋糕和暗夜牌蛋糕。那么把这两种新品加进我们的代码中,很明显,原有代码又要进行修改。所以,我们还需要进一步的改进。

抽象工厂

以光明为例,为了面向接口并满足需求,我们需要新建一个更加抽象的工厂——光明工厂。这里为了更具体,我们就叫他光明下午茶工厂(BrightTeaFactory。那么该工厂自然也就不止能生产果汁,还能够生产蛋糕。当然,接口层次也需要做相应的升级,需要添加下午茶工厂接口。

public interface TeaFactory {//下午茶工厂接口
     Juice createJuice();// 生产果汁对象
     Cake createCake();// 生产蛋糕对象
}

而那些想要生产下午茶的工厂,同理,自己去实现该接口,然后重写上自己的方法就好了。
需要注意的是,虽然现在工厂升级了,能生产更多的产品(有更多的函数),但在该工厂中的方法里,也并不是直接调用new方法来生产,而是依然使用原来的工厂,比如:

public class BrightTeaFactory implements TeaFactory, {
    @Override
    public void createJuice() {// 生产光明果汁
    	return BrightJuiceFactory.creatJuice();
    	//不使用如下方式直接创建对象
		//return new BrightJuice("果汁师Tony","左边第2个桃子","糖浆20g","100ml水","红色色素","秘制配方1");
    }
    @Override
    public void createCake() {// 生产光明蛋糕
		return BrightCakeFactory.creatCake();
    }
}

所以说,抽象工厂又称为工厂的工厂或超级工厂
在想享用下午茶时,只需要这样(以光明牌为例):

Juice bJuice = BrightTeaFactory实例.createJuice();//得到 BrightJuice对象
Cake bCake = BrightTeaFactory实例.createCake();//得到 BrightCake对象
bJuice.drink();// 喝光明果汁
bCake.eat();// 吃光明蛋糕

这种结构的搭建,主要解决的问题是——在原有逻辑和结构优势的基础上,当产品增多的时候(比如:多了蛋糕这一产品),如何减少代码量的修改以及保证代码的秩序性

总结

简单工厂没有被算在23种设计模式之中,它主要解决了对象创建过于复杂的问题,初步实现了对象创建细节与使用的分离。
工厂在简单工厂的优势上,又实现了在添加相似厂家时,程序能依然保持"面向对象设计"的相关原则。
抽象工厂在工厂模式的优势上,又实现了在添加产品时,程序能依然保持"面向对象设计"的相关原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值