工廠設計模式案例詳解,不服來辯!
本文轉載自微信公眾號「Java極客技術」,作者鴨血粉絲 。轉載本文請聯系Java極客技術公眾號。
工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一,今天我們一起來徹底解析一下它。
一、介紹
從名稱上,顧名思義就是創建產品,按類別分為簡單工廠模式、工廠方法模式、抽象工廠模式,主要功能都是幫助我們把對象的實例化操作單獨抽取出來,優化系統架構,增強系統的擴展性。
下面,我們一起來看看各個模式的使用方式。
二、簡單工廠模式
簡單工廠模式,對象創建管理方式最為簡單,因為其僅僅簡單的對不同類對象的創建進行了一層薄薄的封裝。該模式通過向工廠傳遞類型來指定要創建的對象。
- 創建一個接口
- public interface Product {
- void operation1();
- void operation2();
- }
- 創建實現接口的實體類
- public class ConcreateProductA implements Product{
- @Override
- public void operation1() {
- System.out.println("產品A,執行任務1");
- }
- @Override
- public void operation2() {
- System.out.println("產品A,執行任務2");
- }
- }
- public class ConcreateProductB implements Product{
- @Override
- public void operation1() {
- System.out.println("產品B,執行任務1");
- }
- @Override
- public void operation2() {
- System.out.println("產品B,執行任務2");
- }
- }
- 創建一個工廠,生成基于給定信息的實體類的對象
- public class SimpleFactory {
- //使用 create 方法獲取形狀類型的對象
- public Product create(String productType){
- if(productType == null){
- return null;
- }
- if(productType.equalsIgnoreCase("productA")){
- return new ConcreateProductA();
- }
- if(productType.equalsIgnoreCase("productB")){
- return new ConcreateProductB();
- }
- return null;
- }
- }
- 編寫客戶端測試類,使用該工廠,通過傳遞類型信息來獲取實體類的對象
- public class FactoryPatternDemo {
- public static void main(String[] args) {
- SimpleFactory simpleFactory = new SimpleFactory();
- //獲取 productA 的對象
- Product productA = simpleFactory.create("productA");
- //調用 productA 的 operation1、operation2 方法
- productA.operation1();
- productA.operation2();
- //獲取 productB 的對象
- Product productB = simpleFactory.create("productB");
- //調用 productB 的 operation1、operation2 方法
- productB.operation1();
- productB.operation2();
- }
- }
- 執行程序,輸出結果:
- 產品A,執行任務1
- 產品A,執行任務2
- 產品B,執行任務1
- 產品B,執行任務2
當然,還可以將創建對象方式進行改進,將SimpleFactory類創建對象的方式改成如下方式:
- public class SimpleFactory {
- //反射機制獲取實體類
- public <T> T createByClazzName(Class<? extends T> clazz){
- T obj = null;
- try {
- obj = (T) Class.forName(clazz.getName()).newInstance();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return obj;
- }
- }
這樣做的好處是,當有新的產品加入時,不用修改工廠類,在調用的時候,采用如下方式即可獲取對象!
- Product product = new SimpleFactory().create("類名.class");
三、工廠方法模式
和簡單工廠模式中工廠負責生產所有產品相比,工廠方法模式將生成具體產品的任務分發給具體的產品工廠。
- 創建一個工廠接口
- public interface FactoryProduct {
- Product create();
- }
- 創建實現接口的實體類
- public class ConcreateFactoryA implements FactoryProduct{
- @Override
- public Product create() {
- return new ConcreateProductA();
- }
- }
- public class ConcreateFactoryB implements FactoryProduct{
- @Override
- public Product create() {
- return new ConcreateProductB();
- }
- }
- 編寫客戶端測試類,使用該工廠,通過傳遞類型信息來獲取實體類的對象
- public class FactoryPatternDemo {
- public static void main(String[] args) {
- //獲取 productA 的對象
- Product productA = new ConcreateFactoryA().create();
- //調用 productA 的 operation1、operation2 方法
- productA.operation1();
- productA.operation2();
- //獲取 productB 的對象
- Product productA = new ConcreateFactoryB().create();
- //調用 productB 的 operation1、operation2 方法
- productB.operation1();
- productB.operation2();
- }
- }
- 執行程序,輸出結果:
- 產品A,執行任務1
- 產品A,執行任務2
- 產品B,執行任務1
- 產品B,執行任務2
四、抽象工廠模式
抽象工廠模式主要是應對產品族概念提出來的。提供一個創建一系列相關或相互依賴的對象。
- 為形狀創建一個接口
- public interface Shape {
- void draw();
- }
- 創建實現接口的實體類
- public class Rectangle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Rectangle::draw() method.");
- }
- }
- public class Square implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Square::draw() method.");
- }
- }
- public class Circle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Circle::draw() method.");
- }
- }
- 為顏色創建一個接口
- public interface Color {
- void fill();
- }
- 創建實現接口的實體類
- public class Red implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Red::fill() method.");
- }
- }
- public class Green implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Green::fill() method.");
- }
- }
- public class Blue implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Blue::fill() method.");
- }
- }
- 為 Color 和 Shape 對象創建抽象類來獲取工廠
- public abstract class AbstractFactory {
- public abstract Color getColor(String color);
- public abstract Shape getShape(String shape) ;
- }
- 創建擴展了 AbstractFactory 的工廠類,基于給定的信息生成實體類的對象
- public class ShapeFactory extends AbstractFactory {
- @Override
- public Shape getShape(String shapeType){
- if(shapeType == null){
- return null;
- }
- if(shapeType.equalsIgnoreCase("CIRCLE")){
- return new Circle();
- } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
- return new Rectangle();
- } else if(shapeType.equalsIgnoreCase("SQUARE")){
- return new Square();
- }
- return null;
- }
- @Override
- public Color getColor(String color) {
- return null;
- }
- }
- public class ColorFactory extends AbstractFactory {
- @Override
- public Shape getShape(String shapeType){
- return null;
- }
- @Override
- public Color getColor(String color) {
- if(color == null){
- return null;
- }
- if(color.equalsIgnoreCase("RED")){
- return new Red();
- } else if(color.equalsIgnoreCase("GREEN")){
- return new Green();
- } else if(color.equalsIgnoreCase("BLUE")){
- return new Blue();
- }
- return null;
- }
- }
- 創建一個工廠創造器/生成器類,通過傳遞形狀或顏色信息來獲取工廠
- public class FactoryProducer {
- public static AbstractFactory getFactory(String choice){
- if(choice.equalsIgnoreCase("SHAPE")){
- return new ShapeFactory();
- } else if(choice.equalsIgnoreCase("COLOR")){
- return new ColorFactory();
- }
- return null;
- }
- }
- 使用 FactoryProducer 來獲取 AbstractFactory,通過傳遞類型信息來獲取實體類的對象
- public class AbstractFactoryPatternDemo {
- public static void main(String[] args) {
- //獲取形狀工廠
- AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
- //獲取形狀為 Circle 的對象
- Shape shape1 = shapeFactory.getShape("CIRCLE");
- //調用 Circle 的 draw 方法
- shape1.draw();
- //獲取形狀為 Rectangle 的對象
- Shape shape2 = shapeFactory.getShape("RECTANGLE");
- //調用 Rectangle 的 draw 方法
- shape2.draw();
- //獲取形狀為 Square 的對象
- Shape shape3 = shapeFactory.getShape("SQUARE");
- //調用 Square 的 draw 方法
- shape3.draw();
- //獲取顏色工廠
- AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
- //獲取顏色為 Red 的對象
- Color color1 = colorFactory.getColor("RED");
- //調用 Red 的 fill 方法
- color1.fill();
- //獲取顏色為 Green 的對象
- Color color2 = colorFactory.getColor("Green");
- //調用 Green 的 fill 方法
- color2.fill();
- //獲取顏色為 Blue 的對象
- Color color3 = colorFactory.getColor("BLUE");
- //調用 Blue 的 fill 方法
- color3.fill();
- }
- }
- 執行程序,輸出結果:
- Inside Circle::draw() method.
- Inside Rectangle::draw() method.
- Inside Square::draw() method.
- Inside Red::fill() method.
- Inside Green::fill() method.
- Inside Blue::fill() method.
五、應用
工廠模式在實際開發中使用非常頻繁,例如 JDK 中的日歷操作,在國際化的時候,獲取本地語言就用到簡單工廠模式。
寫一個獲取測試,如下:
- public static void main(String[] args) {
- //獲取日歷操作類
- Calendar calendar = Calendar.getInstance();
- int year = calendar.get(Calendar.YEAR);
- // 取月份要加1
- int month = calendar.get(Calendar.MONTH) + 1;
- int day = calendar.get(Calendar.DAY_OF_MONTH);
- int hour = calendar.get(Calendar.HOUR_OF_DAY);
- int minute = calendar.get(Calendar.MINUTE);
- int seconds = calendar.get(Calendar.SECOND);
- // 1-7分別代表 -- 星期日,星期一,星期二,星期三,星期四,星期五,星期六
- int week = calendar.get(calendar.DAY_OF_WEEK);
- // 年-月-日
- System.out.println("year = " + year);
- System.out.println("month = " + month);
- System.out.println("day = " + day);
- //時-分-秒
- System.out.println("hour = " + hour);
- System.out.println("minute = " + minute);
- System.out.println("seconds = " + seconds);
- // 星期
- System.out.println("week = " + week);
- }
進入getInstance()方法,在獲取日歷類型的時候,內容如下:
六、小結
工廠模式中,重要的是工廠類,而不是產品類。產品類可以是多種形式,多層繼承或者是單個類都是可以的。
但要明確的,工廠模式的接口只會返回一種類型的實例,這是在設計產品類的時候需要注意的,最好是有父類或者共同實現的接口。
上面介紹的三種工廠模式有各自的應用場景,實際應用時能解決問題滿足需求即可!
七、參考
1、菜鳥教程 - 工廠模式
2、博客園 - alpha_panda - 設計模式之工廠模式