工厂模式是一种创建者模式,是我们常用的模式之一,多用于需要生成复杂对象的地方。理论来说在任何使用A a = new A()的方式都可以使用工厂模式,虽然使用工厂模式可能需要多做一些工作,但是在后续的开发和维护都带来了方便。 工厂模式降低了对象之间的耦合度,由于工厂模式依赖抽象的架构,实例化的任务交由子类去完成,所以有很好的扩展性。
工厂模式分为三类: ①简单工厂模式 ②工厂方法模式 ③抽象工厂模式
三者之间的区别: ①简单工厂模式只有一个工厂类、一个抽象产品类和多个具体产品类。在工厂类中生成各个具体产品。 ②工厂方法模式有一个抽象工厂类,派生出可以生产多种产品的工厂类;有一个抽象产品类,派生出多种具体的产品;一个工厂负责生产一种具体的产品。 ③工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
1.简单工厂模式 简单工厂模式,一个具体工厂类负责生产所有的具体产品。客户端只需要关注生成的具体产品。
- Factory : 负责生产具体的产品工厂
- Product: 抽象的产品类,
- P1: 具体的产品类P1
- P2: 具体的产品类P2
举个例子。 汽车工厂造汽车的例子。 比如你在大众厂里面上班,一开始被分配到了上海大众里面去了,只管Passat和polo两款车型,而且做的事很简单,就是简单开出去测试一下车子的性能。这个时候事务较少,用简单工厂就能搞定了。 package图如下:
- Volkswagen:抽象的大众汽车类
- Passat,Polo:具体的大众汽车类
- ShangHaiVolkswagenFactory: 上海大众汽车工厂
- Client: 客户端类
具体的代码: 抽象产品类: public interface Volkswagen { void drive(); String getName(); } 具体产品类: public class Passat implements Volkswagen { public static final int ID = 0;
@Override public void drive() { System.out.println(“Passat开出去咯,测试成功”); }
@Override public String getName() { return “Passat”; } }
public class Polo implements Volkswagen{ public static final int ID = 1;
@Override public void drive() { System.out.println(“Polo开出去咯,测试成功”); }
@Override public String getName() { return “Polo”; } }
工厂类: public class ShangHaiVolkswagenFactory { public Volkswagen createVolkswagen(int id){ Volkswagen volkswagen = null; switch(id){ case Passat.ID: volkswagen = new Passat(); break; case Polo.ID: volkswagen = new Polo(); break; default: volkswagen = null; } return volkswagen; } }
客户端类: public class Client { public static void main(String[] args) { ShangHaiVolkswagenFactory factory = new ShangHaiVolkswagenFactory();
Volkswagen passat = factory.createVolkswagen(Passat.ID); passat.drive();
Volkswagen polo = factory.createVolkswagen(Polo.ID); System.out.println(polo.getName()); } } 每次测试的时候Client类都跑了一遍,似乎很简单,同样的也方便以后的扩展(添加新的车型的时候),只需要添加一个产品类,然后在工厂里添加响应的逻辑就行了。
注意:对于上面的工厂,可以采用反射的形式去创建产品类,代码如下: public class ShangHaiVolkswagenFactory { //反射得到 public Volkswagen createVolkswagen(Class <? extends Volkswagen> clazz){ Volkswagen volkswagen = null; try { volkswagen = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return volkswagen; } }
简单工厂模式优缺点: 优点:客户端需要什么产品,可以直接得到,逻辑判断在工厂里面。 缺点:扩展性一般,产品都是一个产品族下面的产品,对于不在产品族中的产品,没办法去扩展,另外获得具体某种产品的逻辑放在工厂里面,新添加产品的时候就需要修改工厂里面的代码。
2.工厂方法模式 特点: ①一个抽象产品,派生出多种具体的产品 ②一个抽象工厂,派生出多种生产产品的工厂类 ③一个具体的工厂负责生产一种具体的产品
- AbstractProduct:抽象的产品类
- ProductA:具体的A产品
- ProductB:具体的B产品
- AbstractFactory:抽象工厂类
- FactoryA:具体的生产A产品的工厂类
- FactoryB:具体的生产B产品的工厂类
- Client: 客户端类
举个例子: 还是上面的例子。你在负责上海大众的两款车型,本来就着简单工厂的模式测试车辆的时候,日子过的非常好,可是好景不长,突然有一天领导说:一汽大众厂最近较忙,看你比较清闲,你就顺便把一汽大众的迈腾,和速腾都测一下。本来也挺简单的,就是简单再添加一个Magotan和Sagitar,然后通过工厂生成就行了,可是等你一拿到测试的项目的时候,发现并不是只测试drive,Sagitar和Magotan不仅需要测试drive,而且需要测试brake。好吧,以前写的都不能够用了。这时候就需要将简单工厂模式升级到工厂方法模式,关注点也发生了改变,不再为具体的车辆的,而是一汽大众的车(Magotan和Sagitar)还是上海大众的车(Passat和 Polo)了。 修改过后的package图:
- Volkswagen: 抽象的汽车类
- ShangHaiVolkswagen:上海大众汽车的抽象类
- FAWVolkswagen:一汽大众汽车的抽象类
- Passat,Polo:上海大众厂汽车类的具体类
- Magotan,Sagitar:一汽大众厂汽车的具体类
- VolkswagenFactory:抽象的大众汽车工厂
- ShangHaiVolkswagenFactory:上海大众汽车工厂,主要负责测试Passat和Polo
- FAWVolkswagenFactory:一汽大众的工厂,主要负责测试Magotan和Sagitar
具体的代码: 抽象类: 产品类—Volkswagen类,将Volkswagen类转成抽象类: public abstract class Volkswagen { public abstract void drive(); public abstract String getName(); } 产品类—ShangHaiVolkswagen—上海大众汽车的抽象类: public abstract class ShangHaiVolkswagen implements Volkswagen{
} 产品类—FAWVolkswagen —一汽大众汽车的抽象类,多了一个brake()的方法: public abstract class FAWVolkswagen implements Volkswagen { public abstract void brake(); } 工厂类—VolkswagenFactory : 汽车工厂的抽象类,并将createVolkswagen(Class clazz)声明称final类型。供子类使用: public abstract class VolkswagenFactory {
public abstract Volkswagen createVolkswagen(int productID);
public final Volkswagen createVolkswagen(Class <? extends Volkswagen> clazz){ Volkswagen volkswagen = null; try { volkswagen = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return volkswagen; }; } 实现类: 产品类—上海大众的具体实现类: public class Passat extends ShangHaiVolkswagen { public static final int ID = 0;
@Override public void drive() { System.out.println(“Passat开出去咯,测试成功”); }
@Override public String getName() { return “Passat”; } } public class Polo extends ShangHaiVolkswagen{ public static final int ID = 1;
@Override public void drive() { System.out.println(“Polo开出去咯,测试成功”); }
@Override public String getName() { return “Polo”; } } 产品类—一汽大众的具体实现类: public class Sagitar extends FAWVolkswagen { public static final int ID = 2;
@Override public void drive() { System.out.println(“Sagitar 开出去了,测试成功了”); }
@Override public String getName() { return “Sagitar”; }
@Override public void brake(){ System.out.println(“Sagitar 刹车挺好的,测试通过了”); } }
public class Magotan extends FAWVolkswagen{ public static final int ID = 3;
@Override public void drive() { System.out.println(“Magotan 开出去咯,测试成功了”); }
@Override public String getName() { return “Magotan”; }
@Override public void brake(){ System.out.println(“Magotan 刹车挺好的,测试通过”); } } 工厂类—注意重载方法的返回类型已经修改称对应的产品类,不在是Volkswagen类型了。 ShangHaiVolkswagenFactory—负责生产上海汽车的工厂类: public class ShangHaiVolkswagenFactory extends VolkswagenFactory {
public ShangHaiVolkswagen createVolkswagen(int id){ ShangHaiVolkswagen volkswagen = null; switch(id){ case Passat.ID: volkswagen = new Passat(); break; case Polo.ID: volkswagen = new Polo(); break; default: volkswagen = null; } return volkswagen; } } FAWVolkswagenFactory—负责生产一汽汽车的工厂类: public class FAWVolkswagenFactory extends VolkswagenFactory {
@Override public FAWVolkswagen createVolkswagen(int productID) { FAWVolkswagen volkswagen = null; switch(productID){ case Magotan.ID: volkswagen = new Magotan(); break; case Sagitar.ID: volkswagen = new Sagitar(); break; default: volkswagen = null; } return volkswagen; } } Client类:用来测试 public class Client { public static void main(String[] args) { System.out.println(“开始测试上海大众的车辆”); ShangHaiVolkswagenFactory factory = new ShangHaiVolkswagenFactory(); ShangHaiVolkswagen passat = factory.createVolkswagen(Passat.ID); passat.drive();
ShangHaiVolkswagen polo = factory.createVolkswagen(Polo.ID); polo.drive();
System.out.println(“开始测试一汽大众的车辆”); FAWVolkswagenFactory fawFactory = new FAWVolkswagenFactory();
FAWVolkswagen magotan = fawFactory.createVolkswagen(Magotan.ID); magotan.drive(); magotan.brake(); FAWVolkswagen sagitar = fawFactory.createVolkswagen(Sagitar.ID); sagitar.drive(); sagitar.brake(); } } 可以看出,上例中将工厂抽象出生产上海大众的车子和一汽大众的车子的两个工厂,并将一汽大众和上海大众的车子做了区分,形成两个不同产品族的产品系列,并由两个工厂分别对应去生产。现在无论处理一汽大众的车子还是上海大众的车子,甚至于再加一个进口大众工厂的车子也够用了,以后的扩展也能得到了提升。
工厂模式的优缺点: 优点:扩展性,能够处理不同产品系列的产品,通过具体的工厂去生成不同产品族的产品,扩展性较好。 缺点:类的个数较多。另外一个工厂的只能够生产一个具体的产品。
|