简介:
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
举例:每个汽车4s店和某个品牌工厂之间的关系,每个汽车4s店只会卖同一品牌的汽车,但是如果这一品牌汽车销量不好,效益不佳,那么4s店可以更换进货的工厂,从而更换其售卖的品牌。
分析:每个品牌的汽车都有一个品牌工厂,这些工厂都有一个生产汽车的方法,4s店中应持有工厂的引用,所以这些汽车工厂都应该实现一个汽车工厂接口,这个4s店中持有汽车工厂的接口,以便更换汽车工厂改变品牌。
实现:
汽车工厂是用来生产汽车的,所以首先应该有一个汽车接口,所有汽车都有一个run方法
1 package com.mi.abstractfactory; 2 3 public interface Car { 4 5 void run(); 6 }
实现这个接口创建一款汽车
package com.mi.abstractfactory; /** * 沃尔沃汽车 */ public class VolvoCar implements Car{ @Override public void run() { System.out.println("沃尔沃:别赶路,去感受路!"); } }
有了汽车类了,这样就可以使用工厂来批量生产了,创建一个汽车工厂接口,其中包含一个生产汽车的方法
1 package com.mi.abstractfactory; 2 3 /** 4 * 汽车工厂接口 5 * @author hellxz 6 */ 7 public interface AbstractCarFactory { 8 9 //接口中所有的没有使用权限修饰符的方法,都是public static final的 10 Car getCar(); 11 }
2.实现一个品牌汽车工厂
1 package com.mi.abstractfactory; 2 /** 3 * 沃尔沃汽车工厂 4 */ 5 public class VolvoCarFactory implements AbstractCarFactory { 6 7 @Override 8 public VolvoCar getCar() { 9 return new VolvoCar(); 10 } 11 12 }
3.创建一个汽车4s店,这个店铺需要有一个卖车的方法saleCar(),并持有一个工厂的引用
1 package com.mi.abstractfactory; 2 3 public class SSSS { 4 5 /** 6 * 实现抽象工厂对象的 注入有两种方式,一种是set设值注入,构造方法,都持有接口的引用 7 */ 8 //持有引用,可以根据多态性,传入该接口的实现类型,从而实现不同的效果 9 private AbstractCarFactory carFactory; 10 11 public Car saleCar() { 12 return carFactory.getCar(); //抽象工厂获取方式得到car对象,可以是car的子类,多态 13 } 14 15 public void setCarFactory(AbstractCarFactory carFactory) { 16 this.carFactory = carFactory; 17 } 18 19 }
为了能看出来更换工厂的效果,同理创建一个Benz汽车的类和工厂
1 package com.mi.abstractfactory; 2 3 /** 4 * 奔驰汽车 5 * @author hellxz 6 */ 7 public class BenzCar implements Car { 8 9 @Override 10 public void run() { 11 System.out.println("奔驰:随时准备好上路疾驶!"); 12 } 13 14 }
1 package com.mi.abstractfactory; 2 3 /** 4 * 奔驰汽车工厂 5 * @author hellxz 6 */ 7 public class BenzCarFactory implements AbstractCarFactory { 8 9 @Override 10 public BenzCar getCar() { 11 return new BenzCar(); 12 } 13 14 // 也可以这样写,返回父类的引用,因为多态(动态绑定),在运行的时候会确定该类型 的具体类型 15 /* public Car getCar() { 16 * return new BenzCar(); 17 * } 18 */ 19 20 }
测试类
1 package com.mi.abstractfactory; 2 3 /** 4 * @author hellxz 5 */ 6 public class Test { 7 8 public static void main(String[] args) { 9 SSSS ssss = new SSSS(); 10 // ssss.setCarFactory(new BenzCarFactory()); //奔驰的工厂 11 ssss.setCarFactory(new VolvoCarFactory()); //沃尔沃的工厂 12 Car car = ssss.saleCar(); 13 car.run(); 14 } 15 }
输出:
沃尔沃:别赶路,去感受路!
测试更换工厂,打开注释行,注释掉沃尔沃的工厂行
输出:
奔驰:随时准备好上路疾驶!
总结:
主要解决:主要解决接口选择的问题。
何时使用:一个系统中有多个系列可选择的情况,每次只能选择其中一系列
优点:
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 降低耦合
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 接口 里加代码,又要在具体的里面加代码。
使用场景: 1、更换一整套的产品 2、生成不同操作系统的程序。