1.简单工厂模式
简单工厂模式(Simple Factory Pattren)是指由一个工厂对象决定创建哪一种产品的实例。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数。对于如何创建对象不需要关心。也就是对不同类的对象进行了一次简简单单的封装,我们只需要想这个类传入相应的参数去调用对象即可。
-
例:
场景:假设我们有一个生产自行车的工厂,其中我们会生产诸如山地车、公路车、儿童自行车等等。在未采用工厂模式之前我们的代码实现可能如下边。
这里我们可以定义一个自行车接口:
public interface Bike { public void run(); }定义一个山地车的实现类:
public class MountainBike implements Bike { @Override public void run() { System.out.println("我在骑山地车哟!"); } }编写客户端的调用代码:
public class SimpleFactoryMain { public static void main(String[] args) { Bike cycle = new MountainBike(); cycle.run(); } }
在上面的代码中,父类Bike指向子类MountainBike的引用,客户端的调用代码依赖MountainBike,如果我们的业务越来越多,继续增加车的种类,那岂不是代码会变得越来越臃肿,实现类可能会变成下面这样:
Bike bike1 = new Bike1();
bike1.run();
Bike bike2 = new Bike2();
bike2.run();
Bike bike3 = new Bike3();
bike3.run();
......
......
现在我们要想办法解决这种依赖,把创建的细节隐藏起来。现在我们简单工厂模式来解决这个问题。
基于上面的自行车接口,增加公路车类RoadBike:
public class RoadBike implements Bike {
@Override
public void run() {
System.out.println("我再骑公路自行车!");
}
}
创建工厂类BikeFactory:
public class BikeFactory {
public Bike create(String name) {
if ("MountainBike".equals(name)) {
return new MountainBike();
} else if ("Roadbike".equals(name)) {
return new RoadBike();
} else {
return null;
}
}
}
修改客户端的实现代码如下:
public class SimpleFactoryMain {
public static void main(String[] args) {
BikeFactory bikeFactory = new BikeFactory();
bikeFactory.create("Roadbike");
}
}
客户端实现变简单了,但是如果我们要继续增加自行车的种类,那么每次增加产品都要修改代码的逻辑,不符合开闭原则,所以我们可以利用反射去优化代码:
public class BikeFactory {
public Bike create(String className) {
try {
if (!(null == className || "".equals(className))) {
return (Bike) Class.forName(className).newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
修改客户端代码:
public class SimpleFactoryMain extends BikeFactory {
public static void main(String[] args) {
BikeFactory bikeFactory = new BikeFactory();
Bike bike = bikeFactory.create("com.factory.simplefactory.BikeFactory");
bike.run();
}
}
优化过后增加产品的过程中不需要优化工厂类BikeFactory的代码,但是其中的方法参数是字符串,为了提升可控性,还需要强制进行类型转换。因此需要作出如下修改:
public class BikeFactory {
public Bike create(Class<? extends Bike> clazz) {
try{
if(null != clazz){
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
对客户端实现代码进行优化:
public class SimpleFactoryMain extends BikeFactory {
public static void main(String[] args) {
BikeFactory bikeFactory = new BikeFactory();
Bike bike = bikeFactory.create(RoadBike.class);
bike.run();
}
}
下面来说下简单工厂的缺点:
- 工厂职责过重,不易于扩展复杂的产品结构。
2.工厂方法模式
工厂方法的模式(Factory Method Pattern)是指定义一个创建对象的接口,让实现这个接口的类来决定实例化哪个类,工厂方法模式就将让实例化的过程放到子类中进行。在工厂方法模式中之需关心所用到的产品所对应的工厂,无需关心所创建的细节,而且新加入的产品是符合开闭原则的。
在上边的自行车工厂中,随着产品的增加,每个自行车的使用以及生产过程都会有所不同,也就是说一个工厂中的所负责的事情会变得越来越多,逐渐会变成万能工厂,比如一开始只是组装山地自行车跟公路自行车,后来又增加了越野山地车、小轮车、电动自行车等等。现在,我们要对工厂的职责进行拆分,专人专事,例如山地车只由山地工厂生产,公路车只由公路自行车生产。即对工厂本身也做一个抽象。接下来进行demo的演示
-
例:
先创建BikeFactory接口:
public interface BikeFactory { Bike create(); }在分别创建公路车子工厂类RoadBikeFactory:
public class RoadBikeFactory implements BikeFactory { @Override public Bike create() { return new RoadBike(); } }山地车子工厂类RoadBikeFactory:
public class MountainBikeFactory implements BikeFactory { @Override public Bike create() { return new MountainBike(); } }测试代码如下:
public class FactoryMain { public static void main(String[] args) { BikeFactory bikeFactory = new MountainBikeFactory(); Bike bike = bikeFactory.create(); bike.run(); bikeFactory=new RoadBikeFactory(); bike=bikeFactory.create(); bike.run(); } }工厂方法模式使用以下场景:
- 创建对象需要大量重复的代码。
-
客户端(应用类、应用层)不依赖于产品类实例如被创建、如何被实现等细节。
-
一个类通过子类来决定创建哪个对象。
缺点:
-
类的个数容易增多增加复杂度。
-
增加了系统的抽象度和理解难度。
3.抽象工厂模式
抽象工厂模式(Abastract Factory Pattern)是指是指提供创建一些列的相关的或者相互依赖对象的接口,无需指定他们的具体类。客户端(应用类、应用层)不依赖产品实例如何被创建、如何被实现等细节,强调的是一系列相关的产品对象(属于同一产品族),一起使用创建的对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
这里解释下两个概念:产品等级结构跟产品族。
佳沃山地车 佳沃头盔 佳沃车架 佳沃碳刀 捷安特山地车 捷安特头盔 捷安特车架 捷安特碳刀 喜德盛山地车 喜德盛头盔 喜德盛车架 喜德盛碳刀 -
第一排的佳沃的产品代表一个产品族,有车、头盔等。每一行代表一个产品族。
-
第一列的佳沃、捷安特等自行车,代表的是产品结构。每一列代表一层产品结构。
现在我们用代码简单的实现下,首先创建Tyre:
public interface Tyre { void turn(); }然后创建Helmet:
public interface Helmet { void wear(); }然后创建一个工厂类BikeFactory:
public interface BikeFactory { Helmet createHelmet(); Tyre createTyre(); }接下来创建捷安特产品族的捷安特头盔类GiantHelmet:
public class GiantHelmet implements Helmet { @Override public void wear() { System.out.println("捷安特头盔!"); } }捷安特产品族的捷安特碳刀类GiantTyre:
public class GiantTyre implements Tyre { @Override public void turn() { System.out.println("捷安特碳刀!"); } }创建捷安特的具体工厂GiantFactory:
public class GiantFactory extends BikeFactory { public Tyre crateTyre() { return new GiantTyre(); } public Helmet createHelmet() { return new GiantHelmet(); } }然后创建喜德盛头盔类XDSHelmet:
public class XDSHelmet implements Helmet{ @Override public void wear() { System.out.println("喜德盛头盔!"); } }创建喜德盛轮胎类XDSTyre:
public class XDSTyre implements Tyre { @Override public void turn() { System.out.println("喜德盛轮胎!"); } }创建喜德盛的一个自行车工厂类XDSFactory:
public class XDSFactory implements BikeFactory{ @Override public Helmet createHelmet() { return new XDSHelmet(); } @Override public Tyre createTyre() { return new XDSTyre(); } }客户端调用代码:
public class AbastractMain { public static void main(String[] args) { GiantFactory giantFactory = new GiantFactory(); giantFactory.createHelmet().wear(); giantFactory.crateTyre().turn(); } }运行结果:
捷安特头盔! 捷安特碳刀! Process finished with exit code 0上边的代码完整的描述了两个产品族:捷安特品牌跟喜德盛品牌,也描述了两个产品等级:头盔跟碳刀(轮子)。抽象工厂完美描述了这一场复杂的关系。但是,我们要将车架也加入到工厂呢?那么从抽象工厂类到具体工厂都要进行调整,显然不符合开闭原则。由此得出抽象工厂的缺点。
-
规定了所有可能被创建的产品集合,产品族中扩展新的产品比较困难,需要修改抽象工厂到,具体工厂。
-
增加了系统的难度和可维护性。