工厂方法模式(java实现)

来源:互联网 发布:润网数据 编辑:程序博客网 时间:2024/05/17 16:46

通过封装,继承,多态把程序的耦合度降低,使用设计模式使得程序可维护,可复用,可扩展,灵活性好(传统印刷术的问题在于把所有文字刻在同一版面上造成耦合度过高所致----可维护:只需更改要改之字;可复用:字并非用完就无用,可以在后面的印刷中重复使用;可扩展:文章要加字,只需要另刻字加入即可;灵活性好:只需要将活字移动就可以满足排版要求)

 

实现一个计算机小程序:

public class FaceObject {

public static void main(String[]args) {

Scanner sc =new Scanner(System.in);

System.out.println("请输入数字A");

int numberA =sc.nextInt();

System.out.println("请选择运算符号(+-*/)");

String strOperate =sc.next();

System.out.println("请输入数字B");

int numberB =sc.nextInt();

 

int result = 0;

switch (strOperate) {

case "+":

result = numberA + numberB;

break;

case "-":

result = numberA - numberB;

break;

case "*":

result = numberA * numberB;

break;

case "/":

if (numberB != 0) {

result = numberA / numberB;

} else {

System.out.println("除数不能为0");

}

break;

}

 

System.out.println("结果是:" +result);

}

}

封装

业务的封装:让业务逻辑和界面逻辑分开,让它们之间的耦合度下降,只有分离开,才能达到易维护和扩展.

package cn.jikun.faceobject;

import java.util.Scanner;

public class FaceObject {

private static int getResult(int numberA, String strOperate, int numberB) {

int result = 0;

switch (strOperate) {

case "+":

result = numberA + numberB;

break;

case "-":

result = numberA - numberB;

break;

case "*":

result = numberA * numberB;

break;

case "/":

if (numberB != 0) {

result = numberA / numberB;

} else {

System.out.println("除数不能为0");

}

break;

}

return result;

}

public static void main(String[]args) {

Scanner sc =new Scanner(System.in);

System.out.println("请输入数字A");

int numberA =sc.nextInt();

System.out.println("请选择运算符号(+-*/)");

String strOperate =sc.next();

System.out.println("请输入数字B");

int numberB =sc.nextInt();

int result = 0;

result = FaceObject.getResult(numberA, strOperate, numberB);

System.out.println("结果是:" +result);

}

}

继承

上面的代码,如果想再加上开根运算(sqrt),如何改?可以更改Operation类,在switch中添加一个分支.但是问题来了,你要加一个平方根运算,却需要加减乘除运算都参与编译,如果不小心,把加法算法改成了减法,就糟糕了.

 

Operation运算类

public class Operation {

protected int numberA;

protected int numberB;

public int getResult() {

int result=0;

return result;

}

public int getNumberA() {

return numberA;

}

public void setNumberA(int numberA) {

this.numberA =numberA;

}

public int getNumberB() {

return numberB;

}

public void setNumberB(int numberB) {

this.numberB =numberB;

}

}

 

加法类

public class OperationAdd extends Operation {

public int getResult() {

return numberA +numberB;

}

}

乘法类

public class OperationMultiply extends Operation{

public int getResult() {

return numberA*numberB;

}

}

测试类

public class Demo {

public static void main(String[]args) {

System.out.println("请输入一个数字");

Scanner sc =new Scanner(System.in);

int number1 =sc.nextInt();

System.out.println("请输入操作符(+-*/)");

String strOperate =sc.next();

Operation operator =null;

switch (strOperate) {

case "+":

operator = new OperationAdd();

break;

case "*":

operator = new OperationMultiply();

break;

}

operator.setNumberA(number1);

System.out.println("请输入一个数字");

int number2 =sc.nextInt();

operator.setNumberB(number2);

 

int result =operator.getResult();

System.out.println(result);

 

}

}

简单工厂模式

将上面继承中的测试类中的代码进行改造

简单运算工厂类

public class OperationFactory {

public static Operation createOperation(String operator) {

Operation operate=null;

switch (operator) {

case "+":

operate=new OperationAdd();

break;

case "*":

operate=new OperationMultiply();

break;

}

return operate;

}

}

测试类

public class DemoFactory {

public static void main(String[]args) {

Operation operation =OperationFactory.createOperation("+");

operation.numberA=1;

operation.numberB=2;

int result =operation.getResult();

System.out.println(result);

}

}

总结:

输入运算符号,工厂就实例出合适的对象,通过多态,返回父类的方式就实现了计算器的结果

问题描述:

简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类.就像本例所示,测试类只需要把”+”号给工厂,工厂自动给出了相应的实例,测试类只需要去做运算就可以了,不同的实例会实现不同的运算.那么问题来了,假如再增加一个功能ab次方,我们则需要在工厂类的方法里增加case分支条件,这样做修改了原有的类,这样就违背了开放封闭原则.

思路分析:

既然这个工厂类和switch选择分支耦合,那么我们就对它下手,根据依赖倒转原则,我们把工厂类抽象成一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法.然后,所有要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,于是我们增加一个功能的时候(ab次方),就不需要更改原有的工厂类,只需要增加此功能的运算类(比如OperationAdd)和相应的工厂就可以了

 

工厂方法

定义一个创建对象的接口,让子类决定实例化哪一个类.工厂方法让一个类的实例化延迟到子类.

public interface IFactory {

Operation createOperation();

}

public class AddFactory implements IFactory {

@Override

public Operation createOperation() {

return new OperationAdd();

}

}

public class MultiplyFactory implements IFactory {

@Override

public Operation createOperation() {

return new OperationMultiply();

}

}

public class DemoFactory2 {

public static void main(String[]args) {

IFactory iFactory=new AddFactory();

//对象operation根本不知道具体可以完成什么操作,却可以在运行时很好地完成操作

Operation operation =iFactory.createOperation();

operation.numberA=1;

operation.numberB=2;

int result =operation.getResult();

System.out.println(result);

}

}

工厂方法的好处和弊端

符合了开放封闭原则,从这个角度来讲,的确比简单工厂模式好;但是,工厂方法模式实现时,测试类需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了测试类代码中.你想要加功能,本来是修改工厂类的,现在却是变成了修改测试类,这个问题可以通过反射来解决.

简单工厂和工厂方法的比较

两者都对创建对象的过程进行封装,使得要变换对象时,不需要大的改动就可以实现,降低了测试类和产品对象的耦合.工厂方法模式是简单工厂的进一步的抽象和推广.由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,又克服了它的缺点.但是工厂方法由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量.

抽象工厂方法

需求:当进行相应的操作时,会进行相应的语音播报,比如在进行加法运算,提示”加法”,客户端可以自由选择是否进行语音提示.需要对工厂方法进行改造,将其改造为抽象工厂方法

public interface IFactory {

Operation createOperation();

Speaker createSpeak();

}

public abstract class Speaker {

public abstract void speak();

}

public class SpeakerAdd extends Speaker{

public void speak() {

System.out.println("加法");

}

}

public class SpeakerMultiply extends Speaker{

public void speak() {

System.out.println("乘法");

}

}

public class AddFactory implements IFactory {

@Override

public Operation createOperation() {

return new OperationAdd();

}

public Speaker createSpeak() {

return new SpeakerAdd();

}

}

public class MultiplyFactory implements IFactory {

@Override

public Operation createOperation() {

return new OperationMultiply();

}

@Override

public Speaker createSpeak() {

return new SpeakerMultiply();

}

}

public class DemoFactory3 {

public static void main(String[]args) {

IFactory iFactory=new AddFactory();

//在操作进行时语音播报

Speaker speaker =iFactory.createSpeak();

speaker.speak();

Operation operation =iFactory.createOperation();

operation.numberA=1;

operation.numberB=2;

int result =operation.getResult();

System.out.println(result);

//只进行语音播报(当然也可以只进行操作

 IFactory iFactory2 =new MultiplyFactory();

 Speaker speaker2 =iFactory2.createSpeak();

 speaker2.speak();

}

}

抽象工厂模式:

提供创建一系列相关或者相互依赖的接口,而无需指定它们具体的类

抽象工厂模式的优点:

可以很方便地切换接口中的功能(比如可以只有操作,也可以只有语音,也可以两者同时有)

抽象工厂的缺点:

如果需要加一个语音识别类,如要增加Iidentify,AddIdentify,MultiplyIdentify三个类,还需要更改IFactory,AddFactory,MultiplyFactory三个类,糟糕.还有是客户端里的代码,很多地方都要使用Speaker speaker =iFactory.createSpeak(); Operation operation =iFactory.createOperation();  

难道要在每一个类的开始都需要声明IFactory iFactory=new AddFactory();   吗

使用简单工厂改进抽象工厂方法

去除IFactory,AddFactory,MultiplyFactory三个工厂类

public class SimpleFactory {

public static Operation createOperation(String operator) {

Operation operate=null;

switch (operator) {

case "+":

operate=new OperationAdd();

break;

case "*":

operate=new OperationMultiply();

break;

}

return operate;

}

public static Speaker createSpeaker(String operator) {

Speaker speaker=null;

switch (operator) {

case "+":

speaker=new SpeakerAdd();

break;

case "*":

speaker=new SpeakerMultiply();

break;

}

return speaker;

}

}

public class DemoFactory4 {

public static void main(String[]args) {

// 进行操作

Operation operation =SimpleFactory.createOperation("+");

operation.numberA = 1;

operation.numberB = 2;

int result =operation.getResult();

System.out.println(result);

// 进行语音播报

Speaker speaker =SimpleFactory.createSpeaker("*");

speaker.speak();

Speaker speaker2 =SimpleFactory.createSpeaker("+");

speaker2.speak();

}

}

 

 

 

匿名内部类改造工厂方法

 

public class Operation {

protected int numberA;

protected int numberB;

public int getResult() {

int result=0;

return result;

}

public int getNumberA() {

return numberA;

}

public void setNumberA(int numberA) {

this.numberA =numberA;

}

public int getNumberB() {

return numberB;

}

public void setNumberB(int numberB) {

this.numberB =numberB;

}

}

public interface IFactory {

Operation createOperation();

}

public class OperationAdd extends Operation {

//将构造器设为私有的,因为没有任何必要去创建该类的对象

private OperationAdd() {

}

public int getResult() {

return numberA +numberB;

}

//如果只需要单一的工厂对象,可以设置为static

public static IFactory addFactory=new IFactory() {

public  Operation createOperation() {

return new OperationAdd();

}

};

}

public class OperationMultiply extends Operation{

//将构造器设为私有的,因为没有任何必要去创建该类的对象

private OperationMultiply() {

}

public int getResult() {

return numberA*numberB;

}

//如果只需要单一的工厂对象,可以设置为static

public static IFactory multiplyFactory=new IFactory() {

public Operation createOperation() {

return new OperationMultiply();

}

};

}

原创粉丝点击