前言:
作为一个程序员,相信你已经有所体会,计算机中的一些思想往往源于实际生活。也就是常说的艺术来源
于生活,接下来,通过一些生活中的例子来分析一下我对工厂模式的浅陋见解,如有解释的不到位的地方,
欢迎各位大佬能够指出。
你想建个什么样的工厂?
在这里,假设你是一个汽水销售工厂的老板,汽水自然有各种各样的种类:苹果味汽水、柠檬味汽水、芒
果味汽水,and so on...............
我们就通过这样的设想来建立一个获得更大利润的工厂:
想一下,现在 苹果味汽水和柠檬味汽水工厂 都是独立的,作为汽水销售工厂的老板,肯定是种类越多越
好,但是,由于各种口味的工厂都是相互独立的,所以就需要去逐个工厂进货,现在只有两个工厂的口味,
运输费还不是太多,但是有 100 种口味的呢?作为汽水销售老总的你,愿意去跑 100 家汽水口味工厂
吗?如果您愿意,那么祝您生意兴隆,嘻嘻。
正在你为运费太贵准备撒手不干时,得到小道消息,附近有个工厂生产各种汽水(假设与其他地方汽水
质量一样,嘻嘻,不要在乎小细节),作为老总的你,喜出望外,这样的话,我不是只跟这个工厂合作就行了
。其他的苹果味呀、柠檬味呀,都不用我操心啦,这样运费由原来的 100 缩减到 1 ,是不是自然会赚
大钱呢?
通过上面的例子相信你已经成为一个合格的老总啦。
简单来说,就是:
我们只跟一个工厂合作就行,而这个工厂完成之前与其他工厂合作的要求。
建造工厂:
传统方式创建:
在用工厂模式之前,我们先用普通的方法实现一下我们的需求:
需求如下:
1、汽水的种类有很多(苹果味汽水、柠檬味汽水)。
2、汽水的制作方式(prepare、bake、cut、box)。
3、完成 汽水的订购功能。
作为老总,我们如何用普通的方法实现该需求呢?
首先,每种汽水只是制作方式不同,所以建立一个 abstract Class Water(){}。
苹果味的还是柠檬味的只需 extends Water 即可。
各种口味只是 prepare() -- 原料不同,所以该方法设置成 abstract,其他在抽象类中实现即可
最后订购的功能进行测试即可。
传统方式代码:
1、 abstract Class Water(){}。
package rj.factory.simpleFactory.water;
// 汽水抽象类
public abstract class Water {
// 汽水口味的 name
String name = null;
// 汽水制作的原料准备,由于每种口味的原料不同,所以交给各自的子类进行实现该抽象类
public abstract void prepare();
public void bake() {
System.out.println(name + "制作过程 1 。。。。。。");
}
public void cut() {
System.out.println(name + "制作过程 2 。。。。。。");
}
public void box() {
System.out.println(name + "制作过程 3 。。。。。。");
}
// 获取汽水口味的 name
public void setName(String name) {
this.name = name;
}
}
2、苹果味的还是柠檬味的只需 extends Water 即可 – 目前是两个工厂
AppleWater.java – extends Water(实现准备原料功能)
package rj.factory.simpleFactory.water;
public class AppleWater extends Water{
@Override
public void prepare() {
System.out.println(name + "汽水原料正在准备中!!!");
}
}
OrangeWater.java – extends Water(实现准备原料功能)
package rj.factory.simpleFactory.water;
public class OrangeWater extends Water{
@Override
public void prepare() {
System.out.println(name + "汽水原料正在准备中!!!");
}
}
orderWater.java – 老总开始订购不同的口味:
package rj.factory.simpleFactory.order;
import rj.factory.simpleFactory.water.AppleWater;
import rj.factory.simpleFactory.water.OrangeWater;
import rj.factory.simpleFactory.water.Water;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class OrderWater {
// 获取控制台的输入
String orderType = null;
// 根据不同的需求产生不同的对象
Water water = null;
public OrderWater() throws IOException {
do{
// 订购不同的口味都需要亲自跑一趟,工厂模式主要在这里优化
orderType = getType();
if(orderType.equals("apple")) {
water = new AppleWater();
} else if(orderType.equals("orange")) {
water = new OrangeWater();
} else {
break;
}
// 执行产品的各个流程
water.setName(orderType);
water.prepare();
water.bake();
water.cut();
water.box();
} while(true);
}
// 通过控制台进行输入不同的口味
public String getType() throws IOException {
BufferedReader strain = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input water type:");
String str = strain.readLine();
return str;
}
}
Test.java
import org.junit.Test;
import rj.factory.simpleFactory.order.OrderPizza;
import rj.factory.simpleFactory.order.OrderWater;
import rj.factory.simpleFactory.order.SimpleFactory;
import java.io.IOException;
public class FactoryTest {
// 老总的工厂
public static void main(String[] args) throws IOException {
new OrderWater();
}
}
简单工厂模式创建:
想一下我们最初的举例,类比一下,就是如果有 100 种口味的产品,我们就需要在下面这个地方创建
100 个对象:
这里只是一个店需要的,如果你以后做大做强了,有100家分店,在每家分店都需要创建 100个对象,这是不是就有点麻烦啦。如果我们在这个地方交给一个工厂,每家店和 1 个工厂对接还是跟 100 个工厂对接,当然是跟 1 个工厂对接方便啦(理解这点很重要)。
在这个地方用 简单工厂模式 优化:
首先要有一个让老总喜出望外的总工厂:
package rj.factory.simpleFactory.order;
import rj.factory.simpleFactory.water.AppleWater;
import rj.factory.simpleFactory.water.OrangeWater;
import rj.factory.simpleFactory.water.Water;
// 简单工厂
public class WaterFactory {
// 根据不同的需要 new 不同的对象(这些都由工厂实现,老总不需要知道为什么)
// 也就是说不用老总一个一个跑腿啦,(不在需要手动一直 new 了)
public Water createFactory(String orderType) {
Water water = null;
if(orderType.equals("apple")) {
water = new AppleWater();
} else if(orderType.equals("orange")) {
water = new OrangeWater();
}
return water;
}
}
可以开开心心的和大工厂合作啦,再也不用担心运费啦
package rj.factory.simpleFactory.order;
import rj.factory.simpleFactory.water.AppleWater;
import rj.factory.simpleFactory.water.OrangeWater;
import rj.factory.simpleFactory.water.Water;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class OrderWater {
// 获取控制台的输入
String orderType = null;
// 根据不同的需求产生不同的对象
Water water = null;
// 汽水工厂总厂(让老总喜出望外的地方)
WaterFactory waterFactory = null;
public void setWaterFactory(WaterFactory waterFactory) {
this.waterFactory = waterFactory;
}
public OrderWater(WaterFactory waterFactory) throws IOException {
do{
orderType = getType();
// 向工厂传递类型,又大工厂进行 new (寻找小工厂进行生产,老总不用管啦)
// 主要是在这里优化
water = waterFactory.createFactory(orderType);
if(water != null) {
water.setName(orderType);
water.prepare();
water.bake();
water.cut();
water.box();
} else {
System.out.println("Sorry,暂时没有您想要的口味。。。。");
break;
}
} while(true);
}
// 通过控制台进行输入不同的口味
public String getType() throws IOException {
BufferedReader strain = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input water type:");
String str = strain.readLine();
return str;
}
}
Test.java:
import org.junit.Test;
import rj.factory.simpleFactory.order.OrderPizza;
import rj.factory.simpleFactory.order.OrderWater;
import rj.factory.simpleFactory.order.SimpleFactory;
import rj.factory.simpleFactory.order.WaterFactory;
import java.io.IOException;
public class FactoryTest {
public static void main(String[] args) throws IOException {
// 肯定需要一个工厂(只不过由原来的多个工厂成了只和一个工厂进行合作)
new OrderWater(new WaterFactory());
}
}
赚钱啦!
你可能会有疑问:这个并没有简化多少呀,在 WaterFactory 中要有新口味的汽水增加的话不是还需要
手动 new 吗? 是的,但是如果有 100 个老总呢?成千上万个呢?这时候如果采用传统的方法,每个
老总的场子都需要 new 100 个,用 WaterFactory 后,只需要导个包就 OK 啦,是不是工厂模式就更
适用啦。
后记:
嘻嘻,废话说了这么多,实际上就是大佬们常说的 解耦 ,也就是降低耦合性,更利于我们的维护,因为
我们维护系统的最好少修改原先的代码,就像你正在开黑,这时停电啦(可能有点不恰当,嘻嘻,但是还
比较好理解的)。
后面还有 工厂方法模式和工厂抽象模式,实际上都是在简单工厂模式上的进一步深化,之后会补上。
如果本篇文章对你有帮助,不要忘记点个赞哦 ^_^!
加油!