解决的问题:
● 将“类实例化的操作”与“适用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。
● 即使用者可直接消费产品而不需要知道其生产的细节。
简单工厂模式:定义一个创建对象的类,由这个类来封装实例化对象的行为(代码)。
工厂类角色Creator:工厂类在客户端的直接控制下(Create方法)创建产品对象。
抽象产品拥有角色Product:定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
具体产品角色ConcreteProduct:定义工厂具体加工出的对象。
首先是一部分最简单的加减乘除的代码
继承思想的编程
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner=new Scanner(System.in);
System.out.println("请输入数字A:");
String strNumberA=scanner.nextLine();
System.out.println("请选择运算符号(+、-、*、/)");
String strOperator=scanner.nextLine();
System.out.println("请输入数字B:");
String strNumberB=scanner.nextLine();
Operation oper;
oper=OperationFacotry.createOperate(strOperator.charAt(0));
oper.setNumberA(Double.parseDouble(strNumberA));
oper.setNumberB(Double.parseDouble(strNumberB));
System.out.println("结果是:"+oper.getRseult());
}
}
abstract class Operation{
//两个Number属性,主要用于计算器的前后数
private double numberA=0;
private double numberB=0;
boolean flag=true;
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;
}
//虚方法GetResult(),用于得到结果
public abstract double getRseult();
}
//加法类,继承运算类
class OperationAdd extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()+getNumberB();
}
}
//减法类,继承运算类
class OperationSub extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()-getNumberB();
}
}
//乘法类,继承运算类
class OperationMul extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()*getNumberB();
}
}
//除法类,继承运算类
class OperationDiv extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()/getNumberB();
}
}
//简单工厂类
class OperationFacotry{
public static Operation createOperate(char operate) {
Operation oper=null;
switch(operate) {
case'+':oper=new OperationAdd();break;
case'-':oper=new OperationSub();break;
case'*':oper=new OperationMul();break;
case'/':oper=new OperationDiv();break;
}
return oper;
}
}
加减乘除都写成运算类Operation的子类,它们继承运算类后,重写getResult(方法,这栏如果要修改任何一算法,就不需要提供其他算法的代码了。
有了简单工厂类如果我们像增加更加复杂的运算,只需要增加相应的运算子类和扩展工厂类就可以了。
//增加具体运算类OperationMN
//m的n次方类,继承运算类
class OperationMN extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double r=1;
double m=getNumberA();
int n=(int)getNumberB();
for(int i=1;i<n;i++)
r=r*m;
return r;
}
}
//简单运算工厂类
class OperationFactory{
public static Operation createOperate(char operate){
Operation oper = null;
switch(operate){
case'+':oper = new OperationAdd();break;
case'-':oper = new OperationSub();break;
case'*':oper = new OperationMul();break;
case'/':oper = new OperationDiv();break;
}
return oper;
}
}
以上方法对扩展开放,但是也对修改开放,违背了封闭-开放原则
再次修改之后的代码:
package gongchang1;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner=new Scanner(System.in);
System.out.println("请输入数字A:");
String strNumberA=scanner.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperator=scanner.nextLine();
System.out.println("请输入数字B:");
String strNumberB=scanner.nextLine();
IFactory operFactory=null;
switch(strOperator.charAt(0)) {
case'+':operFactory=new AddFactory();break;
case'-':operFactory=new SubFactory();break;
case'*':operFactory=new MulFactory();break;
case'/':operFactory=new DivFactory();break;
}
Operation oper=operFactory.createOperation();
oper.setNumberA(Double.parseDouble(strNumberA));
oper.setNumberB(Double.parseDouble(strNumberB));
try {
double result=oper.getRseult();
System.out.println("结果是:"+result);
}catch(Exception e) {
e.printStackTrace();
}
}
}
abstract class Operation{
//两个Number属性,主要用于计算器的前后数
private double numberA=0;
private double numberB=0;
boolean flag=true;
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;
}
//虚方法GetResult(),用于得到结果
public abstract double getRseult();
}
//加法类,继承运算类
class OperationAdd extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()+getNumberB();
}
}
//减法类,继承运算类
class OperationSub extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()-getNumberB();
}
}
//乘法类,继承运算类
class OperationMul extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()*getNumberB();
}
}
//除法类,继承运算类
class OperationDiv extends Operation{
@Override
public double getRseult() {
// TODO Auto-generated method stub
double result=0;
return getNumberA()/getNumberB();
}
}
interface IFactory{
Operation createOperation();
}
class AddFactory implements IFactory{
public Operation createOperation(){
return new OperationAdd();
}
}
class SubFactory implements IFactory{
public Operation createOperation(){
return new OperationSub();
}
}
class MulFactory implements IFactory{
public Operation createOperation(){
return new OperationMul();
}
}
class DivFactory implements IFactory{
public Operation createOperation(){
return new OperationDiv();
}
}
优点:
● 更符合开-闭原则
新增一种产品时,只需要增加相应的吴体产品类和相应的工厂子类即可简单工厂模式霄要修改工厂类的判断逻辑
● 符合单一职责原则
每个具体工厂类只负责创建对应的产品简单工厂中的工厂类存在复杂的if分支逻辑判断不使用静态工厂方法,可以形成基于继承的等级构。简单工厂模式的工厂类使用静态工厂方法。
工厂方法模式是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
缺点:
● 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类霄要编译和运行,会给系统带来一些额外的开销;
● 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,增加了系统的实现难度;
虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的客户端,如果要增加一种产品,仍然霄要修改实例化的具体工厂类;
● 一个具体工厂只能创建一种具体产品。