工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計(jì)模式之一,今天我們一起來徹底解析一下她。
一、介紹
從名稱上,顧名思義就是創(chuàng)建產(chǎn)品,按類別分為簡單工廠模式、工廠方法模式、抽象工廠模式,主要功能都是幫助我們把對象的實(shí)例化操作單獨(dú)抽取出來,優(yōu)化系統(tǒng)架構(gòu),增強(qiáng)系統(tǒng)的擴(kuò)展性。
下面,我們一起來看看各個(gè)模式的使用方式。
二、簡單工廠模式
簡單工廠模式,對象創(chuàng)建管理方式最為簡單,因?yàn)槠鋬H僅簡單的對不同類對象的創(chuàng)建進(jìn)行了一層薄薄的封裝。該模式通過向工廠傳遞類型來指定要?jiǎng)?chuàng)建的對象。
public interface Product { void operation1(); void operation2();}
public class ConcreateProductA implements Product{ @Override public void operation1() { System.out.println("產(chǎn)品A,執(zhí)行任務(wù)1"); } @Override public void operation2() { System.out.println("產(chǎn)品A,執(zhí)行任務(wù)2"); }}
public class ConcreateProductB implements Product{ @Override public void operation1() { System.out.println("產(chǎn)品B,執(zhí)行任務(wù)1"); } @Override public void operation2() { System.out.println("產(chǎn)品B,執(zhí)行任務(wù)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"); //調(diào)用 productA 的 operation1、operation2 方法 productA.operation1(); productA.operation2(); //獲取 productB 的對象 Product productB = simpleFactory.create("productB"); //調(diào)用 productB 的 operation1、operation2 方法 productB.operation1(); productB.operation2(); }}
產(chǎn)品A,執(zhí)行任務(wù)1產(chǎn)品A,執(zhí)行任務(wù)2產(chǎn)品B,執(zhí)行任務(wù)1產(chǎn)品B,執(zhí)行任務(wù)2
當(dāng)然,還可以將創(chuàng)建對象方式進(jìn)行改進(jìn),將SimpleFactory類創(chuàng)建對象的方式改成如下方式:
public class SimpleFactory { //反射機(jī)制獲取實(shí)體類 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; }}
這樣做的好處是,當(dāng)有新的產(chǎn)品加入時(shí),不用修改工廠類,在調(diào)用的時(shí)候,采用如下方式即可獲取對象!
Product product = new SimpleFactory().create("類名.class");
三、工廠方法模式
和簡單工廠模式中工廠負(fù)責(zé)生產(chǎn)所有產(chǎn)品相比,工廠方法模式將生成具體產(chǎn)品的任務(wù)分發(fā)給具體的產(chǎn)品工廠。
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(); //調(diào)用 productA 的 operation1、operation2 方法 productA.operation1(); productA.operation2(); //獲取 productB 的對象 Product productA = new ConcreateFactoryB().create(); //調(diào)用 productB 的 operation1、operation2 方法 productB.operation1(); productB.operation2(); }}
產(chǎn)品A,執(zhí)行任務(wù)1產(chǎn)品A,執(zhí)行任務(wù)2產(chǎn)品B,執(zhí)行任務(wù)1產(chǎn)品B,執(zhí)行任務(wù)2
四、抽象工廠模式
抽象工廠模式主要是應(yīng)對產(chǎn)品族概念提出來的。提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴的對象。
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."); }}
public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ;}
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; }}
public class AbstractFactoryPatternDemo { public static void main(String[] args) { //獲取形狀工廠 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //獲取形狀為 Circle 的對象 Shape shape1 = shapeFactory.getShape("CIRCLE"); //調(diào)用 Circle 的 draw 方法 shape1.draw(); //獲取形狀為 Rectangle 的對象 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //調(diào)用 Rectangle 的 draw 方法 shape2.draw(); //獲取形狀為 Square 的對象 Shape shape3 = shapeFactory.getShape("SQUARE"); //調(diào)用 Square 的 draw 方法 shape3.draw(); //獲取顏色工廠 AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //獲取顏色為 Red 的對象 Color color1 = colorFactory.getColor("RED"); //調(diào)用 Red 的 fill 方法 color1.fill(); //獲取顏色為 Green 的對象 Color color2 = colorFactory.getColor("Green"); //調(diào)用 Green 的 fill 方法 color2.fill(); //獲取顏色為 Blue 的對象 Color color3 = colorFactory.getColor("BLUE"); //調(diào)用 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.
五、應(yīng)用
工廠模式在實(shí)際開發(fā)中使用非常頻繁,例如 JDK 中的日歷操作,在國際化的時(shí)候,獲取本地語言就用到簡單工廠模式。
寫一個(gè)獲取測試,如下:
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); //時(shí)-分-秒 System.out.println("hour = " + hour); System.out.println("minute = " + minute); System.out.println("seconds = " + seconds); // 星期 System.out.println("week = " + week);}
進(jìn)入getInstance()方法,在獲取日歷類型的時(shí)候,內(nèi)容如下:
六、小結(jié)
工廠模式中,重要的是工廠類,而不是產(chǎn)品類。產(chǎn)品類可以是多種形式,多層繼承或者是單個(gè)類都是可以的。
但要明確的,工廠模式的接口只會(huì)返回一種類型的實(shí)例,這是在設(shè)計(jì)產(chǎn)品類的時(shí)候需要注意的,最好是有父類或者共同實(shí)現(xiàn)的接口。
上面介紹的三種工廠模式有各自的應(yīng)用場景,實(shí)際應(yīng)用時(shí)能解決問題滿足需求即可!
原文鏈接:https://mp.weixin.qq.com/s/uPl3MpA38ZwOwk6VWtdipA