工厂模式用来解决具有相同特征类的创建问题,分为3中类型:简单工厂模式、工厂方法模式、抽象工厂模式,其中可以把简单工厂模式看做是工厂方法模式的一种特殊情况,抽象工厂模式是在工厂方法下的进一步抽象。
**简单工厂模式:**
1、工厂类角色,用来创建具体产品。
2、抽象产品类,是具体产品类的父类。
3、具体产品类,最终需要生产的对象。
**工厂方法模式:**
1、抽象工厂,是具体工厂类的父类,用来规范生产。
2、具体工厂,实际的生产工厂类。
3、抽象产品,同上。
4、具体产品,同上。
**抽象工厂模式:**
1、抽象工厂,同上
2、具体工厂,同上
3、抽象产品,同上。
4、具体产品,同上。
下面就以以前的生产手机为例演示各种模式的使用方式,首先我们使用简单工厂模式。我们知道手机有不同的品牌和配置,可这我们也可以把它看做共同点,因为他们都有这些属性,所以我们把它抽象为一个抽象产品类Phone,代码如下:
~~~
public abstract class Phone {
String brand, cup;
abstract void call();
abstract void sendMSG();
}
~~~
现在我们需要生产两种手机,一种是苹果6s一种为三星note5,他们是具体的产品,需要实现抽象的产品类,代码如下:
~~~
public class Iphone extends Phone {
@Override
void call() {
Log.e("", "我使用:" + brand + "拨打的电话!它的cup为:" + cup);
}
@Override
void sendMSG() {
Log.e("", "我使用:" + brand + "发送的短信!它的cup为:" + cup);
}
}
~~~
~~~
public class SumPhone extends Phone {
@Override
void call() {
Log.e("", "我使用:" + brand + "拨打的电话!它的cup为:" + cup);
}
@Override
void sendMSG() {
Log.e("", "我使用:" + brand + "发送的短信!它的cup为:" + cup);
}
}
~~~
有了产品后我们还需要一个生产产品的工厂,下面为工厂类:
~~~
public class PhoneFactory {
public static Phone productPhone(String brand) {
switch (brand) {
case "苹果":
Iphone iphone = new Iphone();
iphone.brand="苹果6s";
iphone.cup="A9";
return iphone;
case "三星":
SumPhone sumPhone = new SumPhone();
sumPhone.brand="三星note5";
sumPhone.cup="Exynos7420";
return sumPhone;
default:
return null;
}
}
}
~~~
ok,有了这些之后,我们就可以生产手机,我们只需要告诉工厂我们生产什么牌子的手机,具体怎么去生产是工厂的事我们不需要过多的关注,下面来看Activity里面的代码:
~~~
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view) {
Phone phone = PhoneFactory.productPhone("苹果");
phone.call();
phone.sendMSG();
}
}
~~~
布局文件就一个按钮,点击按钮执行start方法,下面看输出日志:
![](https://box.kancloud.cn/2016-03-18_56eb6b9da93b5.jpg)
ok,因为现在只需要生产两种手机,工厂中的代码不是很多,如果我们要生产多中手机,比如有华为、魅族、小米、大米、黑米等等,一个工厂不可能都会生产所有的手机,即使能生产我们的工厂类也会变得非常的大,不利于我们的修改,既然工厂类只有一个一个product方法用来生产手机,那么我们是不是可以把它抽象出来,作为一个单独的抽象工程类呢?这就形成了工厂方法模式,下面我们在以上的基础上面新建一个ABSFactory类,代码如下:
~~~
public abstract class ABSFactory {
public abstract Phone product(String brand);
}
~~~
然后我们有两个工厂来生产手机,每个工厂能生产的手机不同,FactoryA的代码如下:
~~~
public class FactoryA extends ABSFactory {
public Phone product(String brand) {
switch (brand) {
case "黑米":
MIPhone miPhone = new MIPhone();
miPhone.brand="黑米10s";
miPhone.cup="骁龙820";
return miPhone;
case "三星":
SumPhone sumPhone = new SumPhone();
sumPhone.brand="三星note5";
sumPhone.cup="Exynos7420";
return sumPhone;
default:
return null;
}
}
}
~~~
FactoryB的代码如下:
~~~
public class FactoryB extends ABSFactory {
@Override
public Phone product(String brand) {
switch (brand) {
case "苹果":
Iphone iphone = new Iphone();
iphone.brand = "苹果6S";
iphone.cup = "A9";
return iphone;
case "华为":
HuaWei huaWei = new HuaWei();
huaWei.brand = "华为锅盖手机";
huaWei.cup = "海思119";
return huaWei;
default:
return null;
}
}
}
~~~
两个手机的代码和先前的手机类类似就不贴出来了,下面我们需要生产一个黑米手机,我们只需要在Activity里面把start方法代码改为:
~~~
public void start(View view) {
FactoryA factoryA = new FactoryA();
Phone phone = factoryA.product("黑米");
phone.call();
phone.sendMSG();
}
~~~
然后运行看结果:
![](https://box.kancloud.cn/2016-03-18_56eb6b9dbc79a.jpg)
这里我们就看出来使用工厂模式的好处了吧,我们都没有修改已有的产品类代码,只需要添加新的代码就可以了,而抽象方法的出现,如果在我们需要创建新的手机,而现有的A、B工厂无法生产的时候我们只需要创建一个C工厂就可以搞定了,代码的耦合性是不是变低了呢?那么现在问题来了,工厂如果只会生产手机,势必没有什么竞争,压力超大呐,你像前不久给锤子代工的工厂就挂了,所以工厂老板说了:“同志们!现在光要你们加班是挣不到钱了,我们要做大做强必须要扩展我们的业务,从下周开始我们新开一个生产线用来生产路由器,以后加完班的如果还想加班可以来这条流水线上面加班!”,OMG,虽然广东的小妹妹年轻,也不可以这么蹂躏嘛,老总的一句话工人又要少活好几年了~~~~~~~~~~~也因为老总的这句话,出现一个新的工厂模式:抽象工厂模式,这个模式与工厂方法是极其相似的,只是抽象工程模式可以一次生产好几种对象出来,而工厂方法模式只能生产一种对象,这就是他们最大的不同点,我们来看看ABSFactoryPlus类,他就是超级工程:
~~~
public abstract class ABSFactoryPlus {
public abstract Phone product(String brand);
public abstract Router newProduct(String brand);
}
~~~
一个具体的超级工厂ConreteFactoryPlus诞生了,他里面的代码为:
~~~
public class ConreteFactoryPlus extends ABSFactoryPlus {
@Override
public Phone product(String brand) {
switch (brand) {
case "黑米":
MIPhone miPhone = new MIPhone();
miPhone.brand = "黑米10s";
miPhone.cup = "骁龙820";
return miPhone;
case "三星":
SumPhone sumPhone = new SumPhone();
sumPhone.brand = "三星note5";
sumPhone.cup = "Exynos7420";
return sumPhone;
default:
return null;
}
}
@Override
public Router newProduct(String brand) {
switch (brand) {
case "水星":
MercuryRouter mercuryRouter = new MercuryRouter();
mercuryRouter.brand = "水星300";
mercuryRouter.rate = 300;
return mercuryRouter;
case "Link":
LinkRouter linkRouter = new LinkRouter();
linkRouter.brand = "Link";
linkRouter.rate = 1000;
return linkRouter;
default:
return null;
}
}
}
~~~
它可以同时生产手机和路由器,下面我们来看看Router类的代码:
~~~
public abstract class Router {
String brand;
int rate;
public abstract void rout();
}
~~~
代码很简单,只有一个rout方法,来看看其实现类MercuryRouter:
~~~
public class MercuryRouter extends Router {
@Override
public void rout() {
Log.e("", "我使用:" + brand + "路由器!它的速率为:" + rate+"M");
}
}
~~~
还有一个LinkRouter类似,就不贴出代码了,下面我们就来测试这个超级工厂能不能符合我们的要求,修改start里面的代码如下:
~~~
public void start(View view) {
ConreteFactoryPlus conreteFactoryPlus = new ConreteFactoryPlus();
Router router = conreteFactoryPlus.newProduct("水星");
Phone phone = conreteFactoryPlus.product("苹果");
if (null == phone) {
Log.e("", "对不起,我们无法为你生产该型号的手机!");
} else {
phone.sendMSG();
phone.call();
}
if (null == router) {
Log.e("", "对不起,我们无法为你生产该型号的路由器!");
} else {
router.rout();
}
}
~~~
我们来看运行结构:
![](https://box.kancloud.cn/2016-03-18_56eb6b9dcea47.jpg)
我们看到同时生产了两种产品。搞定!
**总结:**
使用工厂模式会增加我们类的数量,可是却能降低各种类的耦合性,也可以隐藏类的创建过程,用户无需知道类是如何创建的,也无需知道创建的是什么样的类,只需要给参数传进去就可以得到我们的类。以后我们需要创建几种类似的类的时候我们要优先考虑使用工厂类来代替我们直接new!!ok,今天的模式就到这里了,如果你想学到更多的设计模式请关注我的博客,期待我的更新吧!