实验目的
1 .理解软件设计的相关理论 ;
2 .理解面向对象设计原则;
实验内容
1 .简单工厂模式实验:
(1) 参考讲义上的代码,利用简单工厂模式完成计算器应用程序;
(2) 画出计算器程序简单工厂模式的 UML 图,理解各个类之间的关系;
2 .自行设计
(1) 自行设计一个父类和几个子类,利用简单工厂模式完成相应的功能;
题目要求大致是将Comupter_1.java文件使用简单工厂模式进行重构
原来的Comupter_1.java:
import java.util.Scanner;
public class Computer_1 {
public static void main(String[] args) {
try
{
Scanner input =new Scanner(System.in);
System.out.print("请输入数字A: ");
String strNumberA = input.nextLine();
System.out.print("请选择运算符号(+、-、*、/): ");
String strOperate = input.nextLine();
System.out.print("请输入数字B: ");
String strNumberB = input.nextLine();
String strResult = "";
switch (strOperate)
{
case "+":
strResult = Double.toString( Double.valueOf(strNumberA) + Double.valueOf(strNumberB));
break;
case "-":
strResult = Double.toString(Double.valueOf(strNumberA) - Double.valueOf(strNumberB));
break;
case "*":
strResult = Double.toString(Double.valueOf(strNumberA) / Double.valueOf(strNumberB));
break;
case "/":
if (Double.valueOf(strNumberB) != 0)
strResult = Double.toString( Double.valueOf(strNumberA) / Double.valueOf(strNumberB));
else
strResult = "除数不能为零";
break;
}
System.out.println("结果是" + strResult);
}
catch (Exception e)
{
System.out.println("除数不能为零");
}
}
}
原来的java文件“客户端”(输入数字和符号)和“服务端”(具体的运算)都堆在一起,耦合度较高,不够优雅
因此运用继承,多态,简单工厂模式等对该代码进行重构,使其耦合度降低,更易于维护
首先为“加减乘除”四种运算创建不同的子类继承父类Com
各个子类重写父类的getResult()方法用于对数字进行不同运算返回结果
com.java.Entity.Com.java(父类)
package com.java.Entity;
/**
* @projectName: x
* @package: com.java.Entity
* @className: Com
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:12
* @version: 1.0
*/
public class Com {
private String strNumberA;
private String strNumberB;
public String getStrNumberA() {
return strNumberA;
}
public void setStrNumberA(String strNumberA) {
this.strNumberA = strNumberA;
}
public String getStrNumberB() {
return strNumberB;
}
public void setStrNumberB(String strNumberB) {
this.strNumberB = strNumberB;
}
public String getResult(){
return "";
}
}
com.java.Entity.AddCal.java(加法):
package com.java.Entity;
/**
* @projectName: x
* @package: com.java.Entity
* @className: AddCal
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:18
* @version: 1.0
*/
public class AddCal extends Com{
@Override
public String getResult() {
return Double.toString( Double.valueOf(getStrNumberA()) + Double.valueOf(getStrNumberB()));
}
}
com.java.Entity.MinusCal.java(减法):
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: MinusCal
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:18
* @version: 1.0
*/
public class MinusCal extends Com{
@Override
public String getResult() {
return Double.toString( Double.valueOf(getStrNumberA()) - Double.valueOf(getStrNumberB()));
}
}
com.java.Entity.MultiCal.java
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: MultiCal
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:18
* @version: 1.0
*/
public class MultiCal extends Com{
@Override
public String getResult() {
return Double.toString( Double.valueOf(getStrNumberA()) * Double.valueOf(getStrNumberB()));
}
}
com.java.Entity.DevideCal.java
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: DevideCal
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:19
* @version: 1.0
*/
public class DevideCal extends Com{
@Override
public String getResult() {
if (Double.valueOf(getStrNumberB()) != 0){
return Double.toString( Double.valueOf(getStrNumberA()) / Double.valueOf(getStrNumberB()));
}
else {
return "除数不能为零";
}
}
}
核心思想:
然后是工厂类ComFactory,编写返回Com类型的getCalObj方法,之所以要返回Com类型,是因为Com类型是加减乘除四个子类的父类,因此可以新建一个Com()的实例com,然后根据传入不同的运算符为com设置该运算符对应的运算子类,最终return com,返回的com在set了numberA和numberB后,使用getResult即可返回对应运算后的结果(运用到了多态的思想,将子类向上转型)
com.java.factory.ComFactory.java
package com.java.factory;
import com.java.Entity.*;
/**
* @projectName: z
* @package: com.java.factory
* @className: ComFactory
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:13
* @version: 1.0
*/
public class ComFactory {
// 用了多态的思想
public static Com getCalObj(String strOperate){
Com com = new Com();
switch (strOperate)
{
case "+":
com = new AddCal();
break;
case "-":
com = new MinusCal();
break;
case "*":
com = new MultiCal();
break;
case "/":
com = new DevideCal();
break;
}
return com;
}
}
这个就是在终端接收输入和结果输出的代码,注意对于分母为0情况的输出(见注释)
com.java.test.Computer_test.java
package com.java.test;
import com.java.Entity.Com;
import com.java.Entity.DevideCal;
import com.java.factory.ComFactory;
import java.util.Scanner;
/**
* @projectName: g
* @package: com.java.test
* @className: Computer_test
* @author: GCT
* @description: TODO
* @date: 2022/9/7 17:12
* @version: 1.0
*/
public class Computer_test {
public static void main(String[] args) {
try
{
Scanner input =new Scanner(System.in);
System.out.print("请输入数字A: ");
String strNumberA = input.nextLine();
System.out.print("请选择运算符号(+、-、*、/): ");
String strOperate = input.nextLine();
System.out.print("请输入数字B: ");
String strNumberB = input.nextLine();
// String strResult = "";
Com calObj = ComFactory.getCalObj(strOperate);
calObj.setStrNumberA(strNumberA);
calObj.setStrNumberB(strNumberB);
String strResult = calObj.getResult();
// switch (strOperate)
// {
// case "+":
// strResult = Double.toString( Double.valueOf(strNumberA) + Double.valueOf(strNumberB));
// break;
// case "-":
// strResult = Double.toString(Double.valueOf(strNumberA) - Double.valueOf(strNumberB));
// break;
// case "*":
// strResult = Double.toString(Double.valueOf(strNumberA) * Double.valueOf(strNumberB));
// break;
// case "/":
// if (Double.valueOf(strNumberB) != 0)
// strResult = Double.toString( Double.valueOf(strNumberA) / Double.valueOf(strNumberB));
// else
// strResult = "除数不能为零";
// break;
// }
if (strResult.equals("除数不能为零")){
// 对分母为0的情况的处理方法:
// 若分母为0,DevideCal中会返回"除数不能为零"字符串,而不进行除法运算
// 1、手动抛出一个异常让程序捕获,从而跳到catch中输出"除数不能为零" throw new Exception();
// 2、直接输出"除数不能为零" System.out.println("除数不能为零");
// throw new Exception();
System.out.println("除数不能为零");
}
else{
System.out.println("结果是" + strResult);
}
}
catch (Exception e)
{
System.out.println("除数不能为零");
}
}
}
需求描述: 一个模拟买卖披萨的项目:要便于披萨种类的扩展,便于维护
l)披萨的种类很多(比如ChinesePizza、GreekPizza,MexicoPizza等)
2)披萨的制作有prepare,bake,cut,box等步骤 3)完成披萨店订购功能。
首先看看传统方式:
传统方式的优缺点:
1)优点是比较好理解,简单易操作。
2)缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修 改代码,或者尽可能少修改代码,
例如:我们这时要新增加一个Pizza的种类,只要是订购Pizza的代码都需要修改,可维护性和拓展性等不佳 4)改进的思路分析
3)分析:修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizz 的代码,往往有多处。
思路:把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可,其它有创建到Pizza对象的代码就不需要修改了—>简单工厂模式
com.java.Entity.Pizza.java(父类):
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: Pizza
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:41
* @version: 1.0
*/
//将Pizza类做成抽象父类
public abstract class Pizza {
protected String name;
//准备原材料, 不同的披萨不一样,因此做成抽象方法
public abstract void prepare();
public void bake() {
System.out.println(name + "正在烘焙中....");
}
public void cut() {
System.out.println(name + "正在切割中....");
}
//打包
public void box() {
System.out.println(name + "正在打包中....");
}
public void done(){
System.out.println(name+ "已完成!");
}
public void setName(String name) {
this.name = name;
}
}
com.java.Entity.ChinesePizza.java:
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: ChinesePizza
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:40
* @version: 1.0
*/
public class ChinesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("正在准备中国披萨.....");
}
}
com.java.Entity.GreekPizza.java:
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: GreekPizza
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:40
* @version: 1.0
*/
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println("正在准备希腊披萨.....");
}
}
com.java.Entity.MexicoPizza.java:
package com.java.Entity;
/**
* @projectName: g
* @package: com.java.Entity
* @className: MexicoPizza
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:41
* @version: 1.0
*/
public class MexicoPizza extends Pizza {
@Override
public void prepare() {
System.out.println("正在准备墨西哥披萨.....");
}
}
com.java.Factory.SimpleFactory.java:(工厂类)
package com.java.Factory;
/**
* @projectName: g
* @package: com.java.Factory
* @className: SimpleFactory
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:43
* @version: 1.0
*/
import com.java.Entity.ChinesePizza;
import com.java.Entity.GreekPizza;
import com.java.Entity.MexicoPizza;
import com.java.Entity.Pizza;
//简单工厂类
public class SimpleFactory {
//更加orderType 返回对应的Pizza 对象
public Pizza createPizza(String orderType) {
Pizza pizza = null;
System.out.println("正在使用简单工厂模式1");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希腊披萨");
} else if (orderType.equals("cheese")) {
pizza = new ChinesePizza();
pizza.setName(" 奶酪披萨 ");
} else if (orderType.equals("pepper")) {
pizza = new MexicoPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}
//简单工厂模式 也叫 静态工厂模式
public static Pizza createPizza2(String orderType) {
Pizza pizza = null;
System.out.println("正在使用简单工厂模式2(createPizza2为静态方法)");
if (orderType.equals("Greek")) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if (orderType.equals("Chinese")) {
pizza = new ChinesePizza();
pizza.setName("中国披萨");
} else if (orderType.equals("Mexico")) {
pizza = new MexicoPizza();
pizza.setName("墨西哥披萨");
}
return pizza;
}
}
com.java.test.OrderPizza.java:
package com.java.test;
/**
* @projectName: g
* @package: com.java.test
* @className: OrderPizza
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:44
* @version: 1.0
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import com.java.Entity.Pizza;
import com.java.Factory.SimpleFactory;
public class OrderPizza {
// 构造器
// 不使用简单工厂模式
// public OrderPizza() {
// Pizza pizza = null;
// String orderType; // 订购披萨的类型
// do {
// orderType = getType();
// if (orderType.equals("Greek")) {
// pizza = new GreekPizza();
// pizza.setName("希腊披萨");
// } else if (orderType.equals("Chinese")) {
// pizza = new ChinesePizza();
// pizza.setName("中国披萨");
// } else if (orderType.equals("Mexico")) {
// pizza = new MexicoPizza();
// pizza.setName("墨西哥披萨");
// }
// else {
// break;
// }
// //输出pizza 制作过程
// pizza.prepare();
// pizza.bake();
// pizza.cut();
// pizza.box();
// pizza.done();
//
// } while (true);
// }
//定义一个简单工厂对象
SimpleFactory simpleFactory;
Pizza pizza = null;
//构造器
public OrderPizza(SimpleFactory simpleFactory) {
setFactory(simpleFactory);
}
public void setFactory(SimpleFactory simpleFactory) {
String orderType = ""; //用户输入的类型
this.simpleFactory = simpleFactory; //设置简单工厂对象
do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
//输出pizza
if(pizza != null) { //订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.done();
} else {
System.out.println("订购披萨失败");
break;
}
}while(true);
}
// 写一个方法,让用户输入订购披萨的种类
private String getType() {
try {
Scanner input =new Scanner(System.in);
System.out.print("请输入pizza的种类(Chinese,Greek,Mexico):");
String str = input.nextLine();
return str;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
com.java.test.OrderPizza2.java:
package com.java.test;
/**
* @projectName: g
* @package: com.java.test
* @className: OrderPizza2
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:44
* @version: 1.0
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import com.java.Entity.Pizza;
import com.java.Factory.SimpleFactory;
public class OrderPizza2 {
Pizza pizza = null;
String orderType = "";
// 构造器
public OrderPizza2() {
do {
orderType = getType();
pizza = SimpleFactory.createPizza2(orderType);
// 输出pizza
if (pizza != null) { // 订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.done();
} else {
System.out.println(" 订购披萨失败 ");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
Scanner input =new Scanner(System.in);
System.out.print("请输入pizza的种类(Chinese,Greek,Mexico):");
String str = input.nextLine();
return str;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
com.java.test.PizzaStore.java:
package com.java.test;
/**
* @projectName: g
* @package: com.java.test
* @className: PizzaStore
* @author: GCT
* @description: TODO
* @date: 2022/9/7 19:44
* @version: 1.0
*/
//相当于一个客户端,发出订购
public class PizzaStore {
public static void main(String[] args) {
// 不使用简单工厂模式
//new OrderPizza();
//使用简单工厂模式1
// new OrderPizza(new SimpleFactory());
// System.out.println("程序已退出");
//使用简单工厂模式2(createPizza2为静态方法)
new OrderPizza2();
}
}