什么是工厂模式?
工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。它有自己的应用场景。
优点
- 解耦,把对象的创建和使用的过程分开。
- 降低代码重复.
- 增强了系统的扩展性。
缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
应用场景
1.对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。
2.类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
流程
以接口为例:
1.定义超类(接口、抽象类、父类)
2.子类实现接口,重写接口方法
3.创建工厂(factory),通过工厂获得bean
4.测试
代码实现
定义一个形状接口
public interface Shape
{
void draw();
}
接口实现
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("圆形");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("矩形");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("正方形");
}
}
创建工厂,通过工厂得到bean
public hape getShape(String shapeType){
if(shapeType == null){
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 static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
Shape shape2 = shapeFactory.getShape("RECTANGLE");
shape2.draw();
Shape shape3 = shapeFactory.getShape("SQUARE");
shape3.draw();
}
使用枚举优化
-
避免错误调用的发生
-
性能好,使用便捷
-
降低类间耦合
创建枚举
public enum ShapeType {
CIRCLE, RECTANGLE, SQUARE
}
修改工厂方法
//枚举
public static Shape getShape (ShapeType type){
switch(type){
case CIRCLE:
return new Circle();
case RECTANGLE:
return new Rectangle();
case SQUARE:
return new Square();
default:
throw new UnknownTypeException(null, type);
}
}
测试
//枚举
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape = ShapeFactory.getShape(ShapeType.CIRCLE);
//调用 Circle 的 draw 方法
shape1.draw();
工厂模式与springIOC的区别
IOC是使用了反射的技术来动态的生成对象
<bean id="shapeFactory " class="com.li.factory.ShapeFactory "></bean>
工厂模式的对象生成是提前在工厂类中定死的
所以使用起来IOC更加灵活。
总结
- 也许有人说,IoC和工厂模式不是一样的作用吗,用IoC好象还麻烦一点。
举个例子,如果用户需求发生变化,要把Circle类修改一下或者新增一个类。那么前一种工厂模式,就要更改Factory类的方法,并且重新编译布署。而IoC只需 要将class属性改变一下,并且由于IoC利用了Java反射机制,这些对象是动态生成的,这时我们就可以热插拨Circle对象(不必把原程序停止 下来重新编译布署)
只有Java代码发生改变,JVM才需要重新编译布署.而XML文件的修改并没有发生Java代码发生改变,所以JVM不需要重新编译部署. - 也许有人说,即然IoC这么好,那么我把系统所有对象都用IoC方式来生成。
注意,IoC的灵活性是有代价的:设置步骤麻烦、生成对象的方式不直观、反射比正常生成对象在效率上慢一点。因此使用IoC要看有没有必要,我认为比较通用的判断方式是:用到工厂模式的地方都可以考虑用IoC模式。
参考网站
https://www.runoob.com/design-pattern/factory-pattern.html
https://blog.csdn.net/akunshouyoudou/article/details/104249459
https://blog.csdn.net/fmyzc/article/details/79614944
https://www.cnblogs.com/wei1/p/9582093.html