工廠模式是JAVA中最經常使用的設計模式之一,這種設計模式屬於建立性模式,是一種建立對象的最佳方式。在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用同一個接口來指向新建立的對象例如:你在買一輛車時並不須要這輛車的具體實現,只要從工廠裏直接提貨就好。
java
咱們來舉一個簡單的栗子體會一下工廠模式的含義,在這個栗子中咱們建立一個形狀接口及其實現類,還有一個工廠類。設計模式
第一步:建立接口Shape.javaide
public interface Shape { void draw(); }
第二步:建立Shape.java的實現類spa
Circle.java設計
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
Rectangle.java對象
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
Square.java接口
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
第三步:建立一個工廠ShapeFactory1.javaci
public class ShapeFactory1 { private final String CIRCLE = "CIRCLE"; private final String RECTANGLE = "RECTANGLE"; private final String SQUARE = "SQUARE"; /** * 使用getShape()獲取形狀類型對象 * @param shapeType * @return */ public Shape getShape(String shapeType){ if(StringUtils.isEmpty(shapeType)){ 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; } }
第四步:使用該工廠來建立對象get
public class FactoryPatternDemo1 { public static void main(String[] args) { ShapeFactory1 factory1 = new ShapeFactory1(); //獲取circle對象 Shape shape1 = factory1.getShape("circle"); shape1.draw(); //獲取Rectangle對象 Shape shape2 = factory1.getShape("Rectangle"); shape2.draw(); //獲取Square對象 Shape shape3 = factory1.getShape("Square"); shape3.draw(); } }
第五步:驗證輸出
產品
Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.
由此總結工廠模式的優缺點:
優勢:
一、一個調用者只要知道其名字就能夠,不須要知道其建立過程;
二、拓展性高:增長產品時只須要拓展一個工廠類就行了。
缺點:
每次增長一個產品就要新增一個具體類和實現工廠,使得系統中類的個數成倍增長,必定程度上增長了系統的複雜度。
因此,咱們在建立複雜對象時適合使用工廠模式,建立簡單對象時使用new關鍵字來建立。
-----------------------------------------------我是一條分割線-----------------------------------------------
上面的代碼中存在一個很大的問題:每增長一個實現類就要修改ShapeFactory1.java的代碼,這樣是及其不正確的作法,爲了解決這個問題,咱們使用反射機制來改進。
升級版本一:
工廠類:
public class ShapeFactory2 { public static Object getClass(Class<?extends Shape> clazz){ Object obj = null; try { obj = Class.forName(clazz.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return obj; } }
使用工廠:
public class FactoryPatternDemo2 { public static void main(String[] args) { Circle circle = (Circle) ShapeFactory2.getClass(Circle.class); circle.draw(); Rectangle rectangle = (Rectangle) ShapeFactory2.getClass(Rectangle.class); rectangle.draw(); Square square = (Square) ShapeFactory2.getClass(Square.class); square.draw(); } }
這個版本雖然改進了頻繁修改代碼的缺點,但仍是存在一個問題:調用後不能直接拿到想要的對象還要進行類型強轉。此次咱們使用泛型來解決。
升級版本二:
public class ShapeFactory3 { public static <T> T getClass(Class<? extends T> clazz) { T obj = null; try { obj = (T) Class.forName(clazz.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return obj; } }
使用工廠:
public class FactoryPatternDemo3 { public static void main(String[] args) { Circle circle = ShapeFactory3.getClass(Circle.class); circle.draw(); Rectangle rect = ShapeFactory3.getClass(Rectangle.class); rect.draw(); Shape square = ShapeFactory3.getClass(Square.class); square.draw(); } }