工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。
设计意图:有一个接口,它有多个子类,此时定义一个工厂类,该类用于管理子类的创建。
何时使用:不同的条件需要创建不同的实例。
应用场景:
1>日志记录器:日志可以保存到本地硬盘、系统事件与远程服务器等,用户可以选择日志存放到什么地方。即用户不同的想法需要创建不同的实例(硬盘、系统事件、远程服务器等)。
2>数据库访问:数据库的种类有多种,用户根据不同的需要选择不同的数据库0。
3>连接服务器的协议:用户选择不同的协议连接不同的服务器。
实现
1.创建一个shape接口
public interface Shape {
void draw();
}
2.创建接口的实现类
//Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle");
}
}
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle");
}
}
3.创建一个工厂类,用于管理接口子类
//ShapeFactory.java
public class ShapeFactory {
public Shape getShape(String shapeType){
if (shapeType == null) {
return null;
}
//根据不同的条件,创建不同的实例
if (shapeType.equals("circle")) {
return new Circle();
}else if (shapeType.equals("rectangle")) {
return new Rectangle();
}
return null;
}
}
4.使用
//FactoryDemo
public class FactoryDemo {
public static void main(String[] args) {
/**
* 不使用工厂模式
* 假设创建子实例是一个很繁琐的过程
* 则每次要使用一个新实例的时候,都需要做创建新实例重复的过程
*/
Shape shapeN1 = new Circle();
shapeN1.draw();
Shape shapeN2 = new Rectangle();
shapeN2.draw();
/**
* 使用工厂模式
* 创建一个工厂类,完成 创建子类对象的一些繁琐的过程
* 用户只需要知道需要创建一个什么名称的新对象即可
* 这样可以隐藏对象的创建过程
*/
//创建工厂类对象
ShapeFactory shapeFactory = new ShapeFactory();
//获取circle对象,调用它的方法
Shape shape1 = shapeFactory.getShape("circle");
shape1.draw();
//获取rectangle对象,调用它的方法
Shape shape2 = shapeFactory.getShape("rectangle");
shape2.draw();
}
}
5.输出结果
Circle
Rectangle
6.如上的工厂模式(模式1)可以改进 在模式1中,如果用户需要新增一个形状类(如Square.java),则用户需要修改工厂类和新增Square类。 如下模式2,可以改善模式1 修改工厂类如下
public class ShapeFactory {
public static Shape getShapeInstance(String shapeType) {
if (shapeType == null) {
return null;
}
Shape shape = null;
try {
// 利用反射得到图形类型
shape = (Shape) Class.forName("com.readygo.test." + shapeType).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO: handle exception
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return shape;
}
}
则对应的测试为
public class FactoryDemo {
public static void main(String[] args) {
/**
* 对比模式1与模式2
* 模式1:我们创建的形状实例必须是工厂类中定义了的,
* 如果我们需要创建一个新的形状实例,则需要修改工厂类,同时增加这个新的实例
*
* 模式2:利用反射机制得到形状类型,
* 当我们需要增加一种新的形状时,不需要修改工厂类,只需要增加要实现的类即可
* 从而达到了工厂分离的效果
*/
Shape shape = ShapeFactory.getShapeInstance("Rectangle");
if (shape != null) {
shape.draw();
}else
{
System.out.println("不存在这种对象");
}
}
}