1、概述
核心
- 实例化对象不使用new,用工厂方法代替
- 将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
工厂模式满足的OOP原则:
- 开闭原则:一个软件的实体应当对扩展开放,对修改关闭
- 依赖倒置原则:要针对接口编程,不要针对实现编程
- 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信
三种模式:
- 简单(静态)工厂模式
- 用来生产同一等级结构中的任意产品(对于增加新的产品,需要扩展已有代码)
- 工厂方法模式
- 用来生产同一等级结构中的固定产品(支持增加任意产品)
- 抽象工厂模式
- 围绕一个超级工厂创建其他工厂。该超级工厂又成为其他工厂的工厂
应用场景:
- JDK中Calendar的getInstance方法
- JDBC中的Connection对象的获取
- Spring中IOC容器创建管理bean对象
- 反射中Class对象的newInstance方法
2、简单(静态)工厂模式
-
编写Car接口类:Car.java
package pers.mobian.factory; public interface Car { public void show(); }
-
编写具体的汽车类,且该类是Car类的实现类:BenChi.java、AoDi.java
package pers.mobian.factory; public class BenChi implements Car { @Override public void show() { System.out.println("我是奔驰汽车"); } }
package pers.mobian.factory; public class AoDi implements Car { @Override public void show() { System.out.println("我是奥迪汽车"); } }
-
编写对应的汽车工厂类:FactoryCar.java
package pers.mobian.factory; //静态工厂模式 //增加一个新的产品,如果不修改代码,不好处理 public class FactoryCar { //方法一: public static Car getCar(String car) { if (car.equals("奔驰")) { return new BenChi(); } else if (car.equals("奥迪")) { return new AoDi(); } else { return null; } } //方法二: public static Car getBenChi() { return new BenChi(); } public static Car getAoDi() { return new AoDi(); } }
-
编写具体的实现类:FactoryTest01.java
package pers.mobian.factory; public class FactoryTest01 { public static void main(String[] args) { //传统的调用方式 Car car0 = new BenChi(); car0.show(); Car car1 = new BenChi(); car1.show(); System.out.println("======"); //简单工厂类的两种不同实现方式 Car car2 = FactoryCar.getCar("奔驰"); Car car3 = FactoryCar.getCar("奥迪"); car2.show(); car3.show(); System.out.println("-----"); Car car4 = FactoryCar.getAoDi(); Car car5 = FactoryCar.getBenChi(); car4.show(); car5.show(); } }
-
测试结果
我是奔驰汽车 我是奔驰汽车 ====== 我是奔驰汽车 我是奥迪汽车 ----- 我是奥迪汽车 我是奔驰汽车
总结:此方式可以避免了直接new对象,但是一但需要添加汽车类,势必会新增代码,继而不满足OOP的开闭原则,所以引入了工厂方法模式。
3、工厂方法模式
-
编写汽车类和汽车工厂类的接口Car.java、CarFactory.java
package pers.mobian.factory.method; public interface Car { public void show(); }
package pers.mobian.factory.method; public interface CarFactory { public Car getCar(); }
-
编写具体的汽车类,且该类是Car类的实现类:BenChi.java、AoDi.java
package pers.mobian.factory.method; public class AoDi implements Car { @Override public void show() { System.out.println("我是奥迪汽车"); } }
package pers.mobian.factory.method; public class BenChi implements Car { @Override public void show() { System.out.println("我是奔驰汽车"); } }
-
编写对应的汽车工厂类,并且该类是工厂类接口的实现类:AoDiFactory.java、BenChiFactory.java
package pers.mobian.factory.method; public class BenChiFactory implements CarFactory{ @Override public Car getCar() { return new BenChi(); } }
package pers.mobian.factory.method; public class AoDiFactory implements CarFactory { @Override public Car getCar() { return new AoDi(); } }
-
编写具体的实现类:FactoryTest02.java
package pers.mobian.factory.method; public class FactoryTest02 { public static void main(String[] args) { Car car1 = new BenChiFactory().getCar(); car1.show(); Car car2 = new AoDiFactory().getCar(); car2.show(); } }
-
测试结果
我是奔驰汽车 我是奥迪汽车
总结:工厂方法模式在不修改原有代码的基础上,可以更加灵活的添加功能。即同时满足没有直接new对象,也符合开闭原则。但却会出现另一个问题,即增加的类会很多,并且如果在Car类中包含很多的具体实现,就会导致接口过于庞大。继而引入抽象工厂模式。
4、简单工厂模式与工厂方法模式的比较
- 结构复杂度:抽象工厂模式更简单
- 代码复杂度:抽象工厂模式更简单
- 编程复杂度:抽象工厂模式更简单
- 管理上的复杂度;抽象工厂模式更简单
结论:根据设计原则使用工厂方法模式更好,根据实际业务,往往更多的采用简单工厂模式。
抽象工厂模式
5、抽象工厂模式
抽象工厂模式与工厂模式都属于23种设计模式中的创建者模式之一
定义
抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类
适用场景
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现
优点
- 具体产品在应用层的代码隔离,无需关心创建的细节
- 将一个系列的产品统一到一起创建
缺点
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难
- 增加了系统的抽象性和理解难度
-
编写三个接口类:RouteProduct.java、PhoneProduct.java、ProductFactory.java
package pers.mobian.factory.abstract1; public interface RouteProduct { public void statr(); public void close(); public void wifi(); public void set(); }
package pers.mobian.factory.abstract1; public interface PhoneProduct { public void start(); public void close(); public void call(); public void send(); }
package pers.mobian.factory.abstract1; public interface ProductFactory { PhoneProduct phoneProduct(); RouteProduct routeProduct(); }
-
编写PhoneProduct接口类的实现类:XiaomiPhone.java、HuaweiPhone.java
package pers.mobian.factory.abstract1; public class XiaomiPhone implements PhoneProduct { @Override public void start() { System.out.println("小米手机可以开机"); } @Override public void close() { System.out.println("小米手机可以关机"); } @Override public void call() { System.out.println("小米手机可以打电话"); } @Override public void send() { System.out.println("小米手机可以发短信"); } }
package pers.mobian.factory.abstract1; public class HuaweiPhone implements PhoneProduct { @Override public void start() { System.out.println("华为手机可以开机"); } @Override public void close() { System.out.println("华为手机可以关机"); } @Override public void call() { System.out.println("华为手机可以打电话"); } @Override public void send() { System.out.println("华为手机可以发短信"); } }
-
编写RouteProduct接口类的实现类:XiaomiRoute.java、HuaweiRoute.java
package pers.mobian.factory.abstract1; public class XiaomiRoute implements RouteProduct { @Override public void statr() { System.out.println("小米路由器可以开机"); } @Override public void close() { System.out.println("小米路由器可以关机"); } @Override public void wifi() { System.out.println("小米路由器可以打开wifi"); } @Override public void set() { System.out.println("小米路由器可以设置"); } }
package pers.mobian.factory.abstract1; public class HuaweiRoute implements RouteProduct { @Override public void statr() { System.out.println("华为路由器可以开机"); } @Override public void close() { System.out.println("华为路由器可以关机"); } @Override public void wifi() { System.out.println("华为路由器可以打开wifi"); } @Override public void set() { System.out.println("华为路由器可以设置"); } }
-
编写ProductFactory接口类的实现类:XiaomiFactory.java、HuaweiFactory.java
package pers.mobian.factory.abstract1; public class XiaomiFactory implements ProductFactory { @Override public PhoneProduct phoneProduct() { return new XiaomiPhone(); } @Override public RouteProduct routeProduct() { return new XiaomiRoute(); } }
package pers.mobian.factory.abstract1; public class HuaweiFactory implements ProductFactory { @Override public PhoneProduct phoneProduct() { return new HuaweiPhone(); } @Override public RouteProduct routeProduct() { return new HuaweiRoute(); } }
5、编写具体的实现类:FactoryTest03.java
package pers.mobian.factory.abstract1; public class FactoryTest03 { public static void main(String[] args) { System.out.println("========小米生产线========"); XiaomiFactory xiaomiFactory = new XiaomiFactory(); PhoneProduct phoneProduct = xiaomiFactory.phoneProduct(); phoneProduct.call(); RouteProduct routeProduct = xiaomiFactory.routeProduct(); routeProduct.wifi(); System.out.println("========华为生产线========"); HuaweiFactory huaweiFactory = new HuaweiFactory(); PhoneProduct phoneProduct1 = huaweiFactory.phoneProduct(); phoneProduct1.close(); RouteProduct routeProduct1 = huaweiFactory.routeProduct(); routeProduct1.set(); } }
测试结果:
========小米生产线======== 小米手机可以打电话 小米路由器可以打开wifi ========华为生产线======== 华为手机可以关机 华为路由器可以设置
总结:
想要实现某一个功能,只需要关注其工厂类,不需要关注其实现细节。当新增加功能的时候,如生产笔记本,只需要它们各自去实现其笔记本接口,再在抽象工厂类中添加相应的产品即可完成需求。但是,当在抽象工厂类中添加产品的过程 中,就违反了开闭原则。但如果这种改变如果以后是长期稳定的,也是可以进行适当的违反的。