设计模式(二)——工厂设计模式(1)
一、概念
工厂设计模式也是日常开发中常用的设计模式之一。首先我们先来搞清楚什么是工厂设计模式,我们为什么要使用这种模式。
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到降低耦合提高灵活性的目的。
举个例子:我们去买车,车就是一个对象,没有工厂的话,我们就需要自己制造一辆车,也就是New一个对象;但是制造车的过程很复杂,自己制造很麻烦;所以有了工厂,工厂帮我们制造好车,我们只需要对销售员说:我要一辆车。销售员就给了我们一辆车。
二、分类
工厂模式分为3类:
1.简单工厂模式(Simple Factory)
2.工厂方法模式(Factory Method)
3.抽象工厂模式(Abstract Factory)
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
1.工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
2.抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
1.工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
2.工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
三、简单工厂模式
下面用一个例子来带大家讲解简单工厂模式:实现一个工厂制造奥迪Q系列的车。
首先需要一个奥迪Q车系的接口:
abstract class AudiQ {
public AudiQ(){
}
}
然后是我们的具体车系也就是产品类:
public class AudiQ5 extends AudiQ {
public AudiQ5(){
//创建Q5的过程
}
}
public class AudiQ7 extends AudiQ {
public AudiQ7(){
//创建Q7的过程
}
}
车系定义好了,那么还需要有一个工厂类来生产:
public class Factory {
public AudiQ createAudiQ(int type){
switch (type){
case 5:
return new AudiQ5();
case 7:
return new AudiQ7();
}
return null;
}
}
这样一个简单工厂方法就设计好了,当我们需要什么车系直接跟工厂要就可以了:
Factory factory = new Factory();
AudiQ5 audiQ = (AudiQ5) factory.createAudiQ(5);
AudiQ7 Q7 = (AudiQ7) new Factory().createAudiQ(7);
简单工厂模式又称静态工厂方法模式。它存在的目的很简单:定义一个用于创建对象的接口。
它有3个组成部分:
1.抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
2.具体产品角色:工厂类所创建的对象就是此角色的实例,由一个具体类实现。
3.工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品。
这种工厂模式有一个很明显的缺点:每增加一种车型时,都要新建一个具体产品类,并在工厂类中增加相应的创建业务逻辑,这显然是违背开闭原则的。
于是就出现了优化版,工厂方法模式:它将工厂类定义成了接口,每新增车型,就增加该车种类型对工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。
四、工厂方法模式
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
下面继续用上面的例子来介绍工厂方法模式:
首先奥迪Q车系的接口还是一样:
abstract class AudiQ {
public AudiQ(){
}
}
然后是我们的具体车系也就是产品类:
public class AudiQ5 extends AudiQ {
public AudiQ5(){
//创建Q5的过程
}
}
public class AudiQ7 extends AudiQ {
public AudiQ7(){
//创建Q7的过程
}
}
工厂类这里我们用一个接口实现:
interface FactoryAudiQ {
AudiQ createAudiQ();
}
具体的车系工厂:
public class FactoryAudiQ5 implements FactoryAudiQ {
@Override
public AudiQ createAudiQ() {
return new AudiQ5();
}
}
public class FactoryAudiQ7 implements FactoryAudiQ {
@Override
public AudiQ createAudiQ() {
return new AudiQ7();
}
}
这样一个工厂方法模式也设计好了,最后就是使用:
FactoryAudiQ5 factoryAudiQ5 = new FactoryAudiQ5();
AudiQ5 audiQ5 = (AudiQ5) factoryAudiQ5.createAudiQ();
AudiQ7 audiQ7 = (AudiQ7) new FactoryAudiQ7().createAudiQ()
工厂方法模式组成:
1.抽象产品角色:它是具体产品继承的父类或者是实现的接口。
2.具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
3.抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
4.具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品。
总结一下:
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的工厂类。这样便分担了对象承受的压力;而且这样使得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的!
缺点:当产品种类非常多时,需要大量的与之对应的工厂对象。
今天先写到这里,下篇我在写工厂设计模式的第3种模式:抽象工厂模式。