工厂模式是最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式分为简单工厂模式和工厂方法模式两种。
简单工厂模式
简单工厂模式主要有四种角色:
- 抽象产品角色:接口或抽象类,定义一个产品的共有属性;
- 具体产品角色:对抽象产品的具体实现,由工厂类创建;
- 工厂类角色:创建具体产品类,产品都必须由该类实例化;
- 客户端:创建工厂类实例,通过工厂类简介创建产品类;
结构图如下:
创建抽象产品角色:
public interface Shape {
void draw();
}
创建三个具体产品对象:
public class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("draw the Rectangle.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("draw the Square.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("draw the Circle.");
}
}
常见工厂类角色:
public class ShapeFactory {
public final static int TYPE_RECTANGLE = 0;
public final static int TYPE_SQUARE = 1;
public final static int TYPE_CIRLE = 2;
@Override
Shape createShape(int type) {
Shape mShape = null;
switch (type){
case TYPE_RECTANGLE:
mShape = new Rectangle();
break;
case TYPE_SQUARE:
mShape = new Square();
break;
case TYPE_CIRLE:
mShape = new Circle();
break;
}
return mShape;
}
}
客户端代码:
public class FactoryPartternDemo {
public static void main(String[] args){
ShapeFactory mShapeFactory = new ShapeFactory();
Shape mRectangle = mShapeFactory.createShape(ShapeFactory.TYPE_RECTANGLE);
mRectangle.draw();
Shape mSquare = mShapeFactory.createShape(ShapeFactory.TYPE_SQUARE);
mSquare.draw();
Shape mCircle = mShapeFactory.createShape(ShapeFactory.TYPE_CIRLE);
mCircle.draw();
}
}
运行后输出
draw the Rectangle.
draw the Square.
draw the Circle.
工厂模式的优点
假设我们不使用工厂模式,要创建这三个具体产品类对象你可能会这样写:
public class FactoryPartternDemo {
public static void main(String[] args){
Rectangle rectangle = new Rectangle();
rectangle.draw();
Square square = new Square();
square.draw();
Circle circle = new Circle();
circle.draw();
}
}
这样同样是输出了和上面一样的输出结果,而且代码量减少了,看起来好像这种方式会更好是不是。如果这样想的话你就too young too simple了。
根据依赖倒置原则:要依赖抽象,不依赖具体类。
第二种写法客户端FactoryPartternDemo依赖了三个具体类,如下图:
而第一种写法FactoryPartternDemo只依赖了抽象类Shape,它需要什么类型的对象,只需要向ShapeFactory传入一个类型值,就能获取到需要的对象,而不需要关心具体是什么类。
假设后面由于业务扩展,需要增加类似Oval, Rhombus等多个具体产品时,第二种写法会随着业务产品的增加,依赖的类也随着增加,而第一种写法不管增加多少业务类,它还是只依赖Shape抽象类。