Java设计模式之简单工厂模式实验(软件工程综合实践课程第二周)

实验目的
1 .理解软件设计的相关理论 ;
2 .理解面向对象设计原则;
实验内容
1 .简单工厂模式实验:
(1) 参考讲义上的代码,利用简单工厂模式完成计算器应用程序;
(2) 画出计算器程序简单工厂模式的 UML 图,理解各个类之间的关系;
2 .自行设计
(1) 自行设计一个父类和几个子类,利用简单工厂模式完成相应的功能;

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.java.Entity包实现

首先为“加减乘除”四种运算创建不同的子类继承父类Com

各个子类重写父类的getResult()方法用于对数字进行不同运算返回结果

com.java.Entity包参考代码

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 "除数不能为零";
        }

    }
}

com.java.factory包实现

核心思想:
然后是工厂类ComFactory,编写返回Com类型的getCalObj方法,之所以要返回Com类型,是因为Com类型是加减乘除四个子类的父类,因此可以新建一个Com()的实例com,然后根据传入不同的运算符为com设置该运算符对应的运算子类,最终return com,返回的com在set了numberA和numberB后,使用getResult即可返回对应运算后的结果(运用到了多态的思想,将子类向上转型

com.java.factory包参考代码

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;
    }
}

com.java.test包实现

这个就是在终端接收输入和结果输出的代码,注意对于分母为0情况的输出(见注释)

com.java.test包参考代码

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("除数不能为零");
        }
    }
}

UML类图

在这里插入图片描述

运行结果:

在这里插入图片描述
在这里插入图片描述

项目结构

在这里插入图片描述

2 .自行设计

需求描述: 一个模拟买卖披萨的项目:要便于披萨种类的扩展,便于维护
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包参考代码

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包参考代码

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包参考代码

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();
	}

}

项目结构

在这里插入图片描述

运行结果

在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GCTTTTTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值