工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式分为:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂模式:
首先常见一个Car接口,接口中定义一个run()方法:
1 package top.bigking.factory.simpleFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/7 下午3:43 6 **/ 7 public interface Car { 8 public void run(); 9 }
再写两个类实现这个Car接口
1 package top.bigking.factory.simpleFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/7 下午3:44 6 **/ 7 public class Benchi implements Car { 8 @Override 9 public void run() { 10 System.out.println("奔驰"); 11 } 12 }
1 package top.bigking.factory.simpleFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/7 下午3:44 6 **/ 7 public class Byd implements Car { 8 @Override 9 public void run() { 10 System.out.println("比亚迪"); 11 } 12 }
测试如下:
1 /** 2 * @Author ABKing 3 * @Date 2020/2/7 下午3:45 4 **/ 5 public class TestSimpleFactory { 6 @Test 7 public void testNoFactory(){ 8 Car car1 = new Benchi(); 9 Car car2 = new Byd(); 10 car1.run(); 11 car2.run(); 12 13 14 } 15 }
很明显我们可以看到,作为用户来讲,必须知道接口,还要知道实现类。
而我们不希望用户知道这么多,我们需要隐藏这些,由此,我们引入了简单工厂模式:
新建一个工厂类:
1 package top.bigking.factory.simpleFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/7 下午3:48 6 **/ 7 public class CarFactory { 8 public Car getCar(String carName){ 9 if(carName.equals("奔驰")){ 10 return new Benchi(); 11 } 12 else if(carName.equals("比亚迪")){ 13 return new Byd(); 14 } 15 return null; 16 } 17 }
进行测试:
1 package top.bigking.factory.simpleFactory; 2 3 import org.junit.Test; 4 import sun.security.krb5.internal.ccache.CCacheInputStream; 5 6 /** 7 * @Author ABKing 8 * @Date 2020/2/7 下午3:45 9 **/ 10 public class TestSimpleFactory { 11 @Test 12 public void testNoFactory(){ 13 Car car1 = new Benchi(); 14 Car car2 = new Byd(); 15 car1.run(); 16 car2.run(); 17 } 18 @Test 19 public void testCarFactory(){ 20 CarFactory carFactory = new CarFactory(); 21 Car car1 = carFactory.getCar("比亚迪"); 22 Car car2 = carFactory.getCar("奔驰"); 23 car1.run(); 24 car2.run(); 25 } 26 }
这样用户就不必知道具体的实现了,只需要知道相应的接口即可。
但是我们应该注意的是:如果我们需要增加新的车,比如兰博基尼,我们就需要添加一个新的类,并且在修改工厂类
这显然违反了 开闭原则(对扩展开放,对修改关闭)。
所以我们引入了新的工厂模式:
工厂方法模式
把工厂中的方法抽象出来,形成新的类,BenchiFactory和BydFactory
同时,由于这两个类具有相同的抽象意义,我们定义一个接口,CarFactory
1 package top.bigking.factory.factoryMethod; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午5:28 6 **/ 7 public interface CarFactory { 8 public Car getCar(); 9 }
1 package top.bigking.factory.factoryMethod; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午5:25 6 **/ 7 public class BenchiFactory implements CarFactory{ 8 @Override 9 public Car getCar() { 10 return new Benchi(); 11 } 12 }
1 package top.bigking.factory.factoryMethod; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午5:24 6 **/ 7 public class BydFactory implements CarFactory{ 8 @Override 9 public Car getCar() { 10 return new Byd(); 11 } 12 }
编写JUnit测试
1 package top.bigking.factory.factoryMethod; 2 3 import org.junit.Test; 4 5 /** 6 * @Author ABKing 7 * @Date 2020/2/10 下午5:27 8 **/ 9 public class TestFactoryMethod { 10 @Test 11 public void testFactoryMethod(){ 12 Car car1 = new BenchiFactory().getCar(); 13 Car car2 = new BydFactory().getCar(); 14 car1.run(); 15 car2.run(); 16 } 17 }
工厂方法模式的优点是不需要修改已有的代码,满足开闭原则(对扩展开放,对修改关闭),但是缺点是会增加大量的类,对维护增加了难度。
另外还有一种工厂模式:抽象工厂模式
抽象工厂模式是用来增加产品族的,对增加单个产品无能为力
定义引擎的接口及其实现:
1 package top.bigking.factory.abstractFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午10:23 6 **/ 7 public interface Engine { 8 public void start(); 9 public void run(); 10 } 11 class GoodEngine implements Engine{ 12 13 @Override 14 public void start() { 15 System.out.println("好发动机启动!"); 16 } 17 18 @Override 19 public void run() { 20 System.out.println("好发动机运行"); 21 } 22 } 23 class BadEngine implements Engine{ 24 25 @Override 26 public void start() { 27 System.out.println("差发动机启动!"); 28 } 29 30 @Override 31 public void run() { 32 System.out.println("差发动机运行"); 33 } 34 }
定义轮胎的接口及其实现
1 package top.bigking.factory.abstractFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午10:25 6 **/ 7 public interface Tyre { 8 public void roll(); 9 } 10 class GoodTyre implements Tyre{ 11 @Override 12 public void roll() { 13 System.out.println("好轮胎滚动"); 14 } 15 } 16 class BadTyre implements Tyre{ 17 @Override 18 public void roll() { 19 System.out.println("差轮胎滚动"); 20 } 21 }
定义工厂接口
1 package top.bigking.factory.abstractFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午5:28 6 **/ 7 public interface CarFactory { 8 public Engine getEngine(); 9 public Tyre getTyre(); 10 }
写工厂的两个实现,好车和差车
1 package top.bigking.factory.abstractFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午10:10 6 **/ 7 public class GoodCarFactory implements CarFactory { 8 9 @Override 10 public Engine getEngine() { 11 return new GoodEngine(); 12 } 13 14 @Override 15 public Tyre getTyre() { 16 return new GoodTyre(); 17 } 18 }
1 package top.bigking.factory.abstractFactory; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/10 下午10:32 6 **/ 7 public class BadCarFactory implements CarFactory { 8 @Override 9 public Engine getEngine() { 10 return new BadEngine(); 11 } 12 13 @Override 14 public Tyre getTyre() { 15 return new BadTyre(); 16 } 17 }
测试代码:
1 package top.bigking.factory.abstractFactory; 2 3 import org.junit.Test; 4 5 /** 6 * @Author ABKing 7 * @Date 2020/2/10 下午10:34 8 **/ 9 public class TestAbstractFactory { 10 //测试好车 11 @Test 12 public void testGoodCarFactory(){ 13 CarFactory carFactory = new GoodCarFactory(); 14 Engine engine = carFactory.getEngine(); 15 Tyre tyre = carFactory.getTyre(); 16 engine.start(); 17 engine.run(); 18 tyre.roll(); 19 } 20 //测试差车 21 @Test 22 public void testBadCarFactory(){ 23 CarFactory carFactory = new BadCarFactory(); 24 Engine engine = carFactory.getEngine(); 25 Tyre tyre = carFactory.getTyre(); 26 engine.start(); 27 engine.run(); 28 tyre.roll(); 29 } 30 31 }