工厂模式是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(); } }