简单工厂设计模式
concept
简单工厂模式又叫做静态方法模式,属于创建型模式。 它定义了一个工厂类,负责其他的类的实例化,而被实例化的类通常都继承自同一个父类或者实现同一个接口类。
简单工厂设计模式中无需知道具体的子类类名,就可以得到相应的对象。
analyse
简单工厂模式 url 图
ShapeSimpleFactory
(工厂类) : 简单工厂模式的核心。负责所有产品对象(Product)实例化的逻辑;客户端可以通过调用ShapeSimpleFactory
直接取得具体的产品对象(Square
、Triangle
、Cycle
),而不必考虑实例化的细节,实例化的产品对象对应的具体实现类由服务端的工厂方法ShapeSimpleFactory
决定。Shape
(抽象产品) : 是所有产品的父类或者是它们共同的接口。客户端可以用抽象产品去接收他的实现类,从而不必关系实现类具体是哪一个。使客户端与服务器的耦合性得到了很大程度的降低Square
、Triangle
、Cycle
(具体产品) : 简单工厂创建的实例。他们拥有共同的父类或者实现了共同的接口(Shape
)
example
上述url类图具体实现代码如下:
服务端代码
对应的产品抽象类
/**
* TODO :几何图形 接口 == 抽象产品
* @author wang jian
* @version 1.0.0
**/
public interface Shape {
/**
* TODO : 绘制几何图形
* @author Wang jian
* @date 2020/6/12 10:34
**/
void draw();
/**
* TODO : 擦除几何图形
* @author Wang jian
* @date 2020/6/12 10:34
**/
void erase();
}
对应的产品
/**
* TODO :圆
* @author wang jian
* @version 1.0.0
**/
public class Cycle implements Shape {
@Override
public void draw() {System.out.println("Cycle draw");}
@Override
public void erase() {System.out.println("Cycle erase");}
}
/**
* TODO :正方形
* @author wang jian
* @version 1.0.0
**/
public class Square implements Shape {
@Override
public void draw() {System.out.println("Square draw");}
@Override
public void erase() {System.out.println("Square erase");}
}
/**
* TODO :三角形
* @author wang jian
* @version 1.0.0
**/
public class Triangle implements Shape {
@Override
public void draw() {System.out.println("Triangle draw");}
@Override
public void erase() {System.out.println("Triangle erase");}
}
创建几何图形枚举类(emun 与 switch 配合使用)
/**
* TODO : 几何图像枚举类
* @author wang jian
* @version 1.0.0
**/
public enum ShapeEnum {
SQUARE,
TRIANGLE,
CYCLE
}
创建工厂
/**
* TODO : 产品 Shape的工厂
* @author wang jian
* @version 1.0.0
**/
public class ShapeSimpleFactory {
public static Shape getShape(ShapeEnum shapeEnum) {
Shape shape = null;
switch (shapeEnum) {
case SQUARE:
shape = new Square();
break;
case TRIANGLE:
shape = new Triangle();
break;
case CYCLE:
shape = new Cycle();
break;
default:
break;
}
return shape;
}
}
客户端代码
/**
* TODO : 简单工厂设计模式-客户端
*
* @author wang jian
* @version 1.0.0
**/
public class SimpleFactoryClient {
public static void main(String[] args) {
/**
* 简单工厂设计模式:无需知道具体的子类类名,就可以得到相应的对象
*/
Shape shape = ShapeSimpleFactory.getShape(ShapeEnum.CYCLE);
shape.draw();
System.out.println("=========");
shape = ShapeSimpleFactory.getShape(ShapeEnum.SQUARE);
shape.draw();
System.out.println("=========");
shape = ShapeSimpleFactory.getShape(ShapeEnum.TRIANGLE);
shape.draw();
}
}
result
Cycle draw
=========
Square draw
=========
Triangle draw
可以看到,客户端不需要知道某个产品的具体实现类,只用提供某一个产品在客户端对应的参数,工厂就会自动返回具体的实例对象,客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。这样的话,当子类的类名更换或者增加子类时我们都无需修改客户端代码,只需要在简单工厂类上增加一个分支判断代码即可。
优点
- 工厂类可以决定在什么情况下创建哪一个具体的产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅消费产品。
- 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可。降低了耦合度
缺点
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
- 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑【可以利用反射机制解决】,同样破坏了“开闭原则”;在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
就像前面Example里所展示的,客户端如果想要增加一个的产品,那么必须向服务端提出增加产品的请求,服务端不得不对ShapeSimpleFactory
进行修改,这违背了【开闭原则】。所以只有在我们清楚工厂类负责创建的对象比较少(由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂),且后期增加产品的几率微乎其微的情况下,合理使用简单工厂模式是可以的。