简单工厂模式
1.什么是简单工厂模式
简单工厂模式,大白话来说,就是有一个抽象类,这个抽象类定义了一些属性和一些抽象方法。然后有多个不同的子类继承这个抽象类,并重写抽象方法。 当实例化这个抽象类的时候,对抽象类的属性赋予不同的值,再调用抽象方法,这个抽象方法就可以根据属性值来执行出不同的结果。 简单工厂模式其实就是解决到底要实例化谁,将来会不会增加实例化的对象等问题。而这些问题需要考虑用一个单独的类来做这个创造示例的过程,这个就是工厂类。
2.简单工厂代码示例
2.1抽象Animal父类
/**
* Animal接口
*/
public abstract class Animal {
/**
* 定义一个抽象方法,run
* 其子类会重写该方法
*/
public abstract void run();
}
2.2 Dog子类
/**
* 定义Dog类,继承Animal类
*/
public class Dog extends Animal{
/**
* Dog类重写Animal类的run方法
*/
@Override
public void run() {
System.out.println("小狗类被创建了,小狗正在跑");
}
}
2.3Cat子类
/**
* 定义Cat类,实现Animal接口
*/
public class Cat extends Animal{
/**
* Cat类重写Animal的run方法
*/
@Override
public void run() {
System.out.println("小猫类被创建了,小猫正在跑");
}
}
2.4 Animal工厂类
/**
* Animal工厂类,根据传入工厂的不同动物名称,
* 实例化不同的Animal子类对象
*/
public class AnimalFactory {
/**
* 工厂的静态创建对象方法
* @param animalName 动物名称
* @return Animal抽象类的子类实例
*/
public static Animal createAnimal(String animalName){
Animal animal = null;
switch (animalName){
case "dog":
case "小狗":
animal = new Dog();
break;
case "cat":
case "小猫":
animal = new Cat();
break;
}
return animal;
}
}
2.5测试类
public class MainApplication {
public static void main(String[] args) {
// 通过Animal工厂创建一个小猫实例对象出来
Animal factory = AnimalFactory.createAnimal("小猫");
// 执行新实例对象的run方法
factory.run();
}
}
2.6运行结果
3.简单工厂模式UML类图
4.简单工厂模式演化分析
下面以实现一个简单计算器为示例,演示一下简单工厂设计模式的演变过程
4.1实现一个最简单的计算器
/**
* 计算器,简单版本
*/
public class Operation {
public static double getResult(double numberA, double numberB, String operate){
double result = 0D;
switch (operate){
case "+":
result = numberA + numberB;
break;
case "-":
result = numberA - numberB;
break;
case "/":
case "÷":
result = numberA / numberB;
break;
case "*":
case "x":
result = numberA * numberB;
break;
}
return result;
}
}
4.2 紧耦合 VS 松耦合
上面这个简单的计算器,虽然能够实现加减乘除的功能,但是从设计上来说,这个代码结构不够灵活。如果此时需要加一个开根运算,就需要在Operation类中,加上新的switch分支,这样对Operation这个类改动太大,侵入太多,如果不小心修改错位置,改掉了以前的代码,还可能会造成旧功能失效或出现新bug。 为了解决这样的问题,我们就可以使用继承和多态的机制,来解决Operation类耦合过高的问题。
4.2.1Operation父类
public class Operation {
private double numberA = 0D;
private double numberB = 0D;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public double getResult(){
return 0D;
}
}
4.2.2加法子类
public class OperationAdd extends Operation{
@Override
public double getResult() {
return getNumberA() + getNumberB();
}
}
4.2.3减法子类
public class OperationSub extends Operation{
@Override
public double getResult() {
return getNumberA() - getNumberB();
}
}
4.2.4乘法子类
public class OperationMul extends Operation{
@Override
public double getResult() {
return getNumberA() * getNumberB();
}
}
4.2.5除法子类
public class OperationDiv extends Operation{
@Override
public double getResult() {
if (getNumberB() <= 0) {
throw new RuntimeException("除数不能为0");
}
return getNumberA() / getNumberB();
}
}
4.3 简单工厂模式
像上面一步那样将Operation类和加减乘除操作分离开来,就可以达到让加减乘除操作和Operation类解耦的目的。因为这样写了之后,当需要扩展其他运算规则的时候,只需要继承Operation父类,并重写父类的getResult方法,即可实现对计算器功能的扩展,根本不需要修改Operation父类和其他已存在的加减乘除子类,避免了对已有功能造成bug的风险。 但是这样又会引出另一个问题,那就是如何让计算器知道,我们具体想要执行的是哪一个算法逻辑呢? 由这个问题,就可以引出简单工厂模式。就是说到底要实例化谁,将来会不会增加实例化的对象,比如增加开根运算等,展示很容易变化的地方,应该考虑用一个单独的类来做这个创造示例的过程,这个类就是工厂。
4.3.1简单工厂代码示例
public class OperationFactory {
public static Operation createOperate(String operate){
Operation op = null;
switch (operate){
case "+":
op = new OperationAdd();
break;
case "-":
op = new OperationSub();
break;
case "/":
case "÷":
op = new OperationDiv();
break;
case "*":
case "x":
op = new OperationMul();
break;
}
return op;
}
}
4.3.2 Operation工厂使用
public class MainApplication {
public static void main(String[] args) {
Operation operation = OperationFactory.createOperate("+");
operation.setNumberA(1);
operation.setNumberB(2);
System.out.println(operation.getResult());
}
}
在使用了简单工厂模式后,当需要扩展各种复杂运算,比如平方根,立方根,自然对数等等,只需要继承Operate父类并重写getResult接口即可,这样原计算器的功能就可以很容易被扩展,且不会侵入现有功能。