我们来举一个简单的栗子体会一下工厂模式的含义,在这个栗子中我们创建一个形状接口及其实现类,还有一个工厂类。
第一步:创建接口Shape.java
public interface Shape {
void draw();
}第二步:创建Shape.java的实现类
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.java
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;
}
}第四步:使用该工厂来创建对象
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.
由此总结工厂模式的优缺点:
优点:
1、一个调用者只要知道其名字就可以,不需要知道其创建过程;
2、拓展性高:增加产品时只需要拓展一个工厂类就好了。
缺点:
每次增加一个产品就要新增一个具体类和实现工厂,使得系统中类的个数成倍增加,一定程度上增加了系统的复杂度。
所以,我们在创建复杂对象时适合使用工厂模式,创建简单对象时使用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();
}
}原文:http://blog.51cto.com/13593129/2073941