設計模式——Factory工廠模式
工廠模式
實例化對象,用工廠方法代替new操作。定義一個創建對象的接口指向其實現的子類,讓父類決定實例的生成方式,讓子類決定實現的細節。這樣有利於擴展。
工廠模式是Java中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
作爲一種創建類模式,在任何需要生成複雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。
應用實例: 1、JDBC中調用對數據庫操作的API,而不必關係底層實現的是MySQL還是Oracle,只需要傳入對應的類名。
優點: 1、一個調用者想創建一個對象,只要知道其名稱就可以了。 2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以。 3、屏蔽產品的具體實現,調用者只關心產品的接口。
缺點:每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。
Shape.java
定義一個接口,規範對象使用行爲。
public interface Shape {
void draw();
}
兩個實現類
實現相同的接口,細節實現不同的功能。
public class Square implements Shape {
@Override
public void draw() {
System.out.println("我是方形");
}
}
public class Circle implements Shape { @Override public void draw() { System.out.println("我是圓形"); } }
ShapeFactory.java
實現了三個方法分別對應不同的獲取對象的方式,推薦使用第二和第三個方法,使用了反射機制,這樣新增功能,比如三角形時,不用修改工廠類,而使用第一種方法需要修改。
public class ShapeFactory { //使用 getShape 方法獲取形狀類型的對象 public static Shape getShape(String shapeType) { if (shapeType == null) { return null; } if ("Circle".equals(shapeType)) { return new Circle(); } else if ("Square".equals(shapeType)) { return new Square(); } return null; } //根據類名獲取 public static Shape getShapeByClassName(String className){ Shape shape=null; try { shape = (Shape) Class.forName(className).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return shape; } //根據Class類型 獲取 public static <T> T getShape(Class<? extends T> clazz) { T obj = null; try { obj = (T) Class.forName(clazz.getName()).newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return obj; } }
Test.java
測試,輸出爲:
我是圓形
我是方形
我是圓形
public class Test { public static void main(String[] args){ Shape shape1 = ShapeFactory.getShape("Circle"); shape1.draw(); Shape shape2 = ShapeFactory.getShapeByClassName("factory.shapepack.Square"); shape2.draw(); Shape shape3 = ShapeFactory.getShape(Circle.class); shape3.draw(); } }
抽象工廠模式
抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創建其他工廠。該超級工廠又稱爲其他工廠的工廠。
在抽象工廠模式中,接口是負責創建一個相關對象的工廠,不需要顯式指定它們的類。每個生成的工廠都能按照工廠模式提供對象。
能夠提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。在一個工廠裏聚合多個同類產品。這裏理解上有一定困難,打個比方:
工作了,爲了參加一些聚會,肯定有兩套或多套衣服吧,比如說有商務裝(成套,一系列具體產品)、時尚裝(成套,一系列具體產品),即一系列具體產品。假設一種情況,某一個衣櫃(具體工廠)只能存放某一種這樣的衣服(成套,一系列具體產品),每次拿這種成套的衣服時也自然要從這個衣櫃中取出了。用 OO 的思想去理解,所有的衣櫃(具體工廠)都是衣櫃類的(抽象工廠)某一個,而每一件成套的衣服又包括具體的上衣(某一具體產品),褲子(某一具體產品),這些具體的上衣其實也都是上衣(抽象產品),具體的褲子也都是褲子(另一個抽象產品)。
示例代碼,新增一個Color接口和Red和Blue兩個實現類以及ColorFactory工廠類,類似於上面的Shape實現方式。
新增一個AbstractFactory抽象工廠類
public abstract class AbstractFactory { protected abstract Color getColor(String color); protected abstract Shape getShape(String shape) ; }
ColorFactory和ShapeFactory繼承該抽象工廠類,如ColorFactory:
public class ColorFactory extends AbstractFactory { //簡單起見這裏不使用反射機制 public Color getColor (String colorType){ if (colorType == null) { return null; } if ("Red".equals(colorType)) { return new Red(); } else if ("Blue".equals(colorType)) { return new Blue(); } return null; } @Override //getShape不具體實現,讓ShapeFactory去實現 protected Shape getShape(String shape) { return null; } }
新增一個工廠生成器類來獲取對應的具體的工廠
FactoryProducer
public class FactoryProducer { public static AbstractFactory getFactory(String choice){ //這裏簡單起見不使用反射機制 if("Shape".equals(choice)){ return new ShapeFactory(); } else if("Color".equals(choice)){ return new ColorFactory(); } return null; } }
測試輸出:
我是方形
填充紅色
AbstractFactory shapeFactory = FactoryProducer.getFactory("Shape"); shapeFactory.getShape("Square").draw(); AbstractFactory colorFactory = FactoryProducer.getFactory("Color"); colorFactory.getColor("Red").fill();