简单工厂模式是对封装、继承、多态的一个典型的应用,可以作为理解面向对象的开始。
一、简单工厂模式
1.1 对一个简单计算器程序的改进
实现一个有整数加减乘除功能的简单计算器:
public static int compute(int num1, String operator, int num2) throws Exception {
switch (operator) {
case "+":
return num1+num2;
case "-":
return num1-num2;
case "*":
return num1*num2;
case "/":
if (num2 == 0) {
throw new Exception("除数不能为0");
} else {
return num1/num2;
}
default:
throw new Exception("运算符输入错误!");
}
}
这样计算器功能是实现了,但不太好。比如要让另一个程序员增加一个取余操作,则需把这段代码都给他,让他再增加一个case,加减乘除的操作实现方式都被暴露出来,则这个程序员在增加取余操作时,可能不小心会改动之前加减乘除的实现代码,使已有的正确功能出错。
我们来使用面向对象的思维改造出一个可维护、可复用、可扩展、灵活性好的计算器。
1.2 简单工厂模式
工厂模式是最常用的类创建型设计模式,包括抽象工厂模式、工厂方法模式和简单工厂模式这三种,简单工厂模式是其中最简单的一种。
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于创建型模式。但因为工厂类不符合开放-封闭原则,所以不属于GOF23种设计模式。
1.3 简单工厂模式角色
使用简单工厂模式实现计算器的类图:
Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product
Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。例如操作类Operation。
ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。例如四种具体操作类。
在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用new关键字来创建对象,它是工厂模式家族中最简单的一员。
1.4 简单工厂模式实现计算器
1.4.1 抽象出一个操作类
对上面的计算器代码,先找出共性:无论是加、减、乘还是除运算,都是对两个数进行一种操作,然后返回一个结果,于是可以抽象出一个操作类。
public abstract class Operation {
public abstract int operate(int opreateNum1,int opreateNum2) throws Exception;
}
什么时候使用接口,什么时候使用抽象类:
1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。
2.在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。
3.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。
4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。
5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。
7.接口中的方法默认都是 public,abstract 类型的。
1.4.2 实现操作子类
分别实现加减乘除这四种操作的子类。
public class SumOperation extends Operation {
@Override
public int operate(int opreateNum1, int opreateNum2) {
return opreateNum1+opreateNum2;
}
}
public class SubOperation extends Operation {
@Override
public int operate(int opreateNum1, int opreateNum2) {
return opreateNum1-opreateNum2;
}
}
public class MulOperation extends Operation {
@Override
public int operate(int opreateNum1, int opreateNum2) {
return opreateNum1*opreateNum2;
}
}
public class DivOperation extends Operation {
@Override
public int operate(int opreateNum1, int opreateNum2) throws Exception {
if (opreateNum2 == 0) {
throw new Exception("除数不能为0");
}
return opreateNum1/opreateNum2;
}
}
1.4.3 实现工厂类来确定实例化哪个子类
public class OperationFactory {
//虽然也使用了switch语句,但只是用来判断实例化哪个对象,并不会影响到对象内部的实现逻辑
public static Operation newOperationInstance(String operator) throws Exception {
switch (operator) {
case "+":
return new SumOperation();
case "-":
return new S