工厂模式
一 简单工厂
我们去4s店里面买车下订单,然后汽车工厂根据我们的订单来生成对应的车辆。
1 public class CarShop { 2 public Car order(String type){ 3 Car car = null; 4 if("Benz".equals(type)){ 5 car = new BenzCar(); 6 }else if("Tyota".equals(type)){ 7 car = new ToytaCar(); 8 }else{ 9 return car; 10 } 11 car.design(); 12 car.assemble(); 13 car.test(); 14 return car; 15 } 16 }
这样的代码实现,会随着车辆种类的变多变成if else 地狱,后期对车型的维护会变得无比艰难,所有需要创建Car类的地方都要维护到。我们试着将代码中会变化的部分抽离出来并封装:
1 public class SimpleCarFactory { 2 public Car createCar(String type){ 3 Car car = null; 4 if("Benz".equals(type)){ 5 car = new BenzCar(); 6 }else if("Tyota".equals(type)){ 7 car = new ToytaCar(); 8 }else{ 9 return car; 10 } 11 return car; 12 } 13 } 14 public class CarShop { 15 SimpleCarFactory simpleCarFactory; 16 17 public CarShop(SimpleCarFactory simpleCarFactory){ 18 this.simpleCarFactory = simpleCarFactory; 19 } 20 21 public Car order(String type){ 22 Car car = simpleCarFactory.createCar(type); 23 car.design(); 24 car.assemble(); 25 car.test(); 26 return car; 27 } 28 }
这样分离之后,虽然if else地狱依然存在,但是在别的需要创建Car对象的地方就不用重复维护了。
简单工厂模式与其说是一种设计模式,不如说是一种编程习惯。类图如下:
二 工厂模式
当我们的汽车销售形成规模,在各地都需要4s店,而各地对汽车的审美都有自己的要求,即需要一些地方化的服务。我们之前一刀切式地在order方法中根据车型来创建
汽车对象的方式需要进行调整了,因为它不能满足需求了。代码调整如下:
1.将CarShop类中createCar方法抽象出来,让各地的分店自行实现自己的。
1 public abstract class CarShop { 2 public Car order(String type){ 3 Car car = createCar(type); 4 car.design(); 5 car.assemble(); 6 car.test(); 7 return car; 8 } 9 10 public abstract Car createCar(String type); 11 }
2.北京和大连的4s店
1 public class BeijingCarShop extends CarShop { 2 public Car createCar(String type) { 3 Car car = null; 4 if("Benz".equals(type)){ 5 car = new BeijingBenzCar(); 6 }else if("Tyota".equals(type)){ 7 car = new BeijingTyotaCar(); 8 }else{ 9 return car; 10 } 11 return car; 12 13 } 14 } 15 public class DalianCarShop extends CarShop { 16 public Car createCar(String type) { 17 Car car = null; 18 if("Benz".equals(type)){ 19 car = new DalianBenzCar(); 20 }else if("Tyota".equals(type)){ 21 car = new DalianTyotaCar(); 22 }else{ 23 return car; 24 } 25 return car; 26 27 } 28 }
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样程序中超类的代码和子类对象的创建代码就解耦了。
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
设计原则:依赖倒置原则--要依赖抽象,不要依赖具体类。
三 抽象工厂模式
当我们的需求变更为为不同的品牌的车生产不同配置的车时,也就是说同样车型的车,有了不同的配置。配置大概抽出几个,如轮胎,引擎,座椅等。
面向接口设计原则,我们将这些个配置也全都抽象出来,这样上面的工厂模式就不适合了。我们来看看抽象工厂模式。
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
类图如下:
代码实现:
1.配件接口,及高低端配件的实现类
1 //引擎 2 3 public interface Engine { 4 public void run(); 5 public void start(); 6 } 7 8 class LuxuryEngine implements Engine{ 9 10 public void run() { 11 System.out.println("跑得快"); 12 } 13 14 public void start() { 15 System.out.println("启动快"); 16 } 17 } 18 19 class LowEngine implements Engine{ 20 21 public void run() { 22 System.out.println("跑得慢"); 23 } 24 25 public void start() { 26 System.out.println("启动慢"); 27 } 28 } 29 //轮胎 30 public interface Tyre { 31 public void revolve(); 32 } 33 34 class LuxuryTyre implements Tyre{ 35 36 public void revolve() { 37 System.out.println("耐磨"); 38 } 39 } 40 41 class LowTyre implements Tyre{ 42 43 public void revolve() { 44 System.out.println("不耐磨"); 45 } 46 } 47 //座椅 48 public interface Seat { 49 public void message(); 50 } 51 52 class LuxurySeat implements Seat{ 53 54 public void message() { 55 System.out.println("真皮沙发"); 56 } 57 } 58 59 class LowSeat implements Seat{ 60 61 public void message() { 62 System.out.println("塑料沙发"); 63 } 64 }
2.抽象工厂类
1 public interface CarFactory { 2 Engine createEngine(); 3 Tyre createTyre(); 4 Seat createSeat(); 5 }
3.高低端工厂实现类
1 public class LowCarFactory implements CarFactory { 2 public Engine createEngine() { 3 return new LowEngine(); 4 } 5 6 public Tyre createTyre() { 7 return new LowTyre(); 8 } 9 10 public Seat createSeat() { 11 return new LowSeat(); 12 } 13 } 14 public class LuxuryCarFactory implements CarFactory { 15 public Engine createEngine() { 16 return new LuxuryEngine(); 17 } 18 19 public Tyre createTyre() { 20 return new LuxuryTyre(); 21 } 22 23 public Seat createSeat() { 24 return new LuxurySeat(); 25 } 26 }
4.测试
1 public class Client { 2 public static void main(String[] args){ 3 CarFactory factory = new LowCarFactory(); 4 Engine e = factory.createEngine(); 5 e.start(); 6 e.run(); 7 } 8 }
运行结果:
四 总结
要点:
简单工厂模式:虽然某种程度不符合设计原则,但实际使用最多
工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展
抽象工厂模式:不可以增加产品,但可以增加产品族
应用场景:
JDK中Calendar的getInstance方法
JDBC中Connection对象的获取
Spring中IOC容器创建管理bean对象
反射中Class对象的newInstance()