设计模式之工厂方法模式、抽象工厂模式的概念和实现及使用“反射技术+读取配置文件”的方法对工厂模式进行改进(软件工程综合实践课程第三周个人作业)

文章目录

一、实验目的

  1. 理解面向对象设计原则和常用设计模式;
  2. 理解并掌握工厂模式的概念和实现;
  3. 理解并掌握抽象工厂模式的概念和实现;
  4. 理解用反射技术+ 配置文件对工厂模式进行改进的方法;

二、知识总结

完整代码在“三、实验内容”里哦

1、工厂方法模式简介

关于上次作业里面的披萨项目(使用简单工厂模式实现软件工程综合实践课程第二周作业(简单工厂模式实验)

看一个新的需求:
披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza、北京的胡椒pizz或者是伦敦的奶酪pizza、伦敦的胡椒pizza。
思路1
使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory等等.从当前
这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
思路2
使用工厂方法模式

工厂方法模式介绍
1)工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
2)工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
6.2.5工厂方法模式应用案例
1)披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza、北京的胡椒pizza或者是伦敦的奶酪pizza、伦敦的胡椒pizza
2)思路分析图解
在这里插入图片描述

2、抽象工厂模式简介

基本介绍:
1)抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
2)抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
3)从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
4)将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
5)类图
在这里插入图片描述

3、工厂模式小结

1)工厂模式的意义
实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
2)三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式) 3)设计模式的依赖抽象原则

  • 创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。有的书上说的是:变量不要直接持有具体类的引用。
  • 不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
  • 不要覆盖基类中已经实现的方法

4、利用“反射技术+读取配置文件”的方法改进程序

若不使用“反射技术+读取配置文件”的方法,则要对运算符进行手动判断(if…else或者switch之类的)才能新建运算符对应的工厂类
测试程序中:

//        根据不同的符号来获取对应的运算类(将具体逻辑封装到了ComFactory.java)
//        使用“反射技术+读取配置文件”进行改进后就不需要使用这种方法来实现了
            Com com = ComFactory.getCalObj(strOperate,strNumberA,strNumberB);
//        com.setStrNumberA(strNumberA);
//        com.setStrNumberB(strNumberB);

            String result = com.getResult();
            System.out.println(result);

ComFactory.java

package com.java.factory;

import com.java.Entity.*;

/**
 * @projectName: 
 * @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,String strNumberA,String strNumberB){
        Com com = new Com();
        switch (strOperate)
        {
            /**
             * @param strOperate:
             * @return Com
             * @author 
             * @description 已根据抽象工厂模式进行修改
             * @date 2022/9/23 22:28
             * 使用对应的工厂类来new对应的运算类
             * 使用“反射技术+读取配置文件”进行改进后这个类就不需要了
             */
            case "+":
                com = new AddFactory().createCal(strNumberA,strNumberB);
                break;
            case "-":
                com = new MinusFactory().createCal(strNumberA,strNumberB);
                break;
            case "*":
                com = new MultiFactory().createCal(strNumberA,strNumberB);
                break;
            case "/":
                com = new DevideFactory().createCal(strNumberA,strNumberB);
                break;
        }
        return com;
    }
}

这种方法下,如果要对运算类或者工厂类进行增添减少等修改时就要打开该代码对这个switch进行修改,即需要修改程序的源代码,这不符合开闭原则(软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的)

所以我们使用“反射技术+读取配置文件”的方法改进程序:
在测试程序中我们修改为:

//        利用“反射技术+读取配置文件”的方法对上述程序做改进;
//        使用这种方法就不用再像ComFactory.java中那样根据传过去的运算符先判断后再新建对应的类
//        而是直接在配置文件中取到该运算符对应的工厂类名字,根据反射新建一个工厂实例,从而进行具体运算类的新建等操作
            Properties properties = new Properties();
            InputStream is = new FileInputStream(new File("src/com/java/cal.properties"));
            properties.load(is);
            is.close();
            String className = properties.getProperty(strOperate);
            IFactory factory = (IFactory) Class.forName(className).newInstance();
            Com com1 = factory.createCal(strNumberA,strNumberB);
            String strRes = com1.getResult();
            if (strRes.equals("除数不能为零")){
                System.out.println("除数不能为零");
            }
            else{
                System.out.println("结果是" + strRes);
            }

src/com/java/cal.properties:

+=com.java.factory.AddFactory
-=com.java.factory.MinusFactory
*=com.java.factory.MultiFactory
/=com.java.factory.DevideFactory

使用这种方法就不用再像在ComFactory.java中那样根据传过去的运算符先手动判断后再新建对应的类
而是直接在配置文件中获取到该运算符对应的工厂类名字,根据反射新建一个工厂实例,从而进行具体运算类的新建等操作

这样的话在不修改源代码的情况下进行软件中的对象(类,模块,函数等等)的扩展

举个例子(以我这个项目结构为例):
如果想新增一个开方操作的话,需要做以下操作:
1、新建一个继承Com的开方运算类SqrtCal.java(类似AddCal.java,但具体运算不同)
2、新建一个实现IFactory接口的工厂类SqrtFactory.java(类似AddtFactory.java,但具体new的运算类不同)
3、在配置文件中添加一行(假设开方符号为^)
^=com.java.factory.SqrtFactory
然后就完成了!完全不用修改已经写好了的代码,而是“新建文件+修改配置文件”就行了

三、实验内容

1. 工厂模式实验

(1).用工厂设计模式完成计算器程序;
(2).利用“反射技术+读取配置文件”的方法对上述程序做改进;
(3). 项目名为“week3_学号_1”;

参考代码

com.java.Entity包代码

com.java.Entity包内代码没有改,就不贴了,可以在这里面找到:
软件工程综合实践课程第二周作业(简单工厂模式实验)

com.java.factory包代码
com.java.factory.IFactory.java:
package com.java.factory;
import com.java.Entity.Com;

public interface IFactory {
    public Com createCal(String strNumberA,String strNumberB);
}

com.java.factory.AddFactory.java:
package com.java.factory;

import com.java.Entity.AddCal;
import com.java.Entity.Com;

/**
 * @projectName:  
 * @package: com.java.factory
 * @className: AddFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/19 11:36
 * @version: 1.0
 */
public class AddFactory implements IFactory{
    @Override
    public Com createCal(String strNumberA,String strNumberB) {
        Com com = new AddCal();

//        顺便把A和B的值设置到com中,这样在测试类中
//        只要传入strNumberA和strNumberB新建具体计算类的时候就已经完成了数字的设置,然后直接getResult就行
        com.setStrNumberA(strNumberA);
        com.setStrNumberB(strNumberB);
        return com;

    }
}

com.java.factory.MinusFactory.java
package com.java.factory;

import com.java.Entity.AddCal;
import com.java.Entity.Com;
import com.java.Entity.MinusCal;
import com.java.Entity.MultiCal;

/**
 * @projectName:  
 * @package: com.java.factory
 * @className: MinusFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/19 11:36
 * @version: 1.0
 */
public class MinusFactory implements IFactory{
    @Override
    public Com createCal(String strNumberA,String strNumberB) {
        Com com = new MinusCal();
        com.setStrNumberA(strNumberA);
        com.setStrNumberB(strNumberB);
        return com;
    }
}

com.java.factory.MultiFactory.java
package com.java.factory;

import com.java.Entity.AddCal;
import com.java.Entity.Com;
import com.java.Entity.MultiCal;

/**
 * @projectName:  
 * @package: com.java.factory
 * @className: MultiFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/19 11:37
 * @version: 1.0
 */
public class MultiFactory implements IFactory{
    @Override
    public Com createCal(String strNumberA,String strNumberB) {
        Com com = new MultiCal();
        com.setStrNumberA(strNumberA);
        com.setStrNumberB(strNumberB);
        return com;
    }
}

com.java.factory.DevideFactory.java
package com.java.factory;

import com.java.Entity.AddCal;
import com.java.Entity.Com;
import com.java.Entity.DevideCal;

/**
 * @projectName:  
 * @package: com.java.factory
 * @className: DevideFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/19 11:37
 * @version: 1.0
 */
public class DevideFactory implements IFactory{
    @Override
    public Com createCal(String strNumberA,String strNumberB) {
        Com com = new DevideCal();
        com.setStrNumberA(strNumberA);
        com.setStrNumberB(strNumberB);
        return com;
    }
}

com.java.factory.ComFactory.java:

使用反射+配置文件方法的话没有用到这个类

package com.java.factory;

import com.java.Entity.*;

/**
 * @projectName:  
 * @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,String strNumberA,String strNumberB){
        Com com = new Com();
        switch (strOperate)
        {
            /**
             * @param strOperate:
             * @return Com
             * @author  
             * @description 已根据抽象工厂模式进行修改
             * @date 2022/9/23 22:28
             * 使用对应的工厂类来new对应的运算类
             * 使用“反射技术+读取配置文件”进行改进后这个类就不需要了
             */
            case "+":
                com = new AddFactory().createCal(strNumberA,strNumberB);
                break;
            case "-":
                com = new MinusFactory().createCal(strNumberA,strNumberB);
                break;
            case "*":
                com = new MultiFactory().createCal(strNumberA,strNumberB);
                break;
            case "/":
                com = new DevideFactory().createCal(strNumberA,strNumberB);
                break;
        }

        return com;
    }
}

com.java.test包代码
com.java.test.Abs_test.java
package com.java.test;

import com.java.Entity.*;
import com.java.factory.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Scanner;

/**
 * @projectName:  
 * @package: com.java.test
 * @className: Abs_test
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:47
 * @version: 1.0
 */
public class Abs_test {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

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

//        根据不同的符号来获取对应的运算类(将具体逻辑封装到了ComFactory.java)
//        使用“反射技术+读取配置文件”进行改进后就不需要使用这种方法来实现了
            Com com = ComFactory.getCalObj(strOperate,strNumberA,strNumberB);
//        switch (strOperate)
//        {
//            case "+":
//                com = new AddFactory().createCal(strOperate);
//                break;
//            case "-":
//                com = new MinusFactory().createCal(strOperate);
//                break;
//            case "*":
//                com = new MultiFactory().createCal(strOperate);
//                break;
//            case "/":
//                com = new DevideFactory().createCal(strOperate);
//                break;
//        }
//        com.setStrNumberA(strNumberA);
//        com.setStrNumberB(strNumberB);

            String result = com.getResult();
            System.out.println(result);

//        利用“反射技术+读取配置文件”的方法对上述程序做改进;
//        使用这种方法就不用再像ComFactory.java中那样根据传过去的运算符先判断后再新建对应的类
//        而是直接在配置文件中取到该运算符对应的工厂类名字,从而进行具体运算类的新建等操作
            Properties properties = new Properties();
            InputStream is = new FileInputStream(new File("src/com/java/cal.properties"));
            properties.load(is);
            is.close();
            String className = properties.getProperty(strOperate);
            IFactory factory = (IFactory) Class.forName(className).newInstance();
            Com com1 = factory.createCal(strNumberA,strNumberB);
            String strRes = com1.getResult();
            if (strRes.equals("除数不能为零")){
//                对分母为0的情况的处理方法:
//                若分母为0,DevideCal中会返回"除数不能为零"字符串,而直接不进行除法运算
//                1、手动抛出一个异常让程序捕获,从而跳到catch中输出"除数不能为零"  throw new Exception();
//                2、直接输出"除数不能为零"   System.out.println("除数不能为零");

//                throw new Exception();
                System.out.println("除数不能为零");
            }
            else{
                System.out.println("结果是" + strRes);
            }
        }catch (Exception e){
//            除数为0的情况在DevideCal.java运算类中已经处理,所以不在这里处理了
            System.out.println("输入有误!");
        }
    }
}

com.java.test.Computer_test.java

这个是之前的,这次用Abs_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:  
 * @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,strNumberA,strNumberB);

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

配置文件
com/java/cal.properties:
+=com.java.factory.AddFactory
-=com.java.factory.MinusFactory
*=com.java.factory.MultiFactory
/=com.java.factory.DevideFactory

项目结构

在这里插入图片描述

运行结果

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

2、自行设计(披萨店)

(1).自行设计一个父类和几个子类,利用工广模式完成相应的功能:
(2).项目名为“week3学号_2”;

分别使用工厂方法模式和抽象工厂模式对披萨店项目进行改进
关于工厂方法模式和抽象工厂模式的简介和使用“反射技术+读取配置文件”的方法对程序进行改进的方法可以参考“二、知识总结”

① 工厂方法模式的参考代码

com.java.FactoryMethod.Entity包
com.java.FactoryMethod.Entity.Pizza(抽象类)
package com.java.FactoryMethod.Entity;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Entity
 * @className: Pizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 20:00
 * @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 finish(){
        System.out.println(name + " 已完成!");
    }

    public void setName(String name) {
        this.name = name;
    }
}

com.java.FactoryMethod.Entity.BJCheesePizza
package com.java.FactoryMethod.Entity;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Entity
 * @className: BJCheesePizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 19:58
 * @version: 1.0
 */
public class BJCheesePizza extends Pizza {

    @Override
    public void prepare() {
        setName("北京的奶酪pizza");
        System.out.println("北京的奶酪pizza 正在准备原材料...");
    }

}

com.java.FactoryMethod.Entity.BJPepperPizza
package com.java.FactoryMethod.Entity;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Entity
 * @className: BJPepperPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 19:59
 * @version: 1.0
 */
public class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京的胡椒pizza");
        System.out.println("北京的胡椒pizza 正在准备原材料");
    }
}


com.java.FactoryMethod.Entity.LDCheesePizza
package com.java.FactoryMethod.Entity;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Entity
 * @className: LDCheesePizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 19:59
 * @version: 1.0
 */
public class LDCheesePizza extends Pizza{

    @Override
    public void prepare() {
        setName("伦敦的奶酪pizza");
        System.out.println("伦敦的奶酪pizza 正在准备原材料");
    }
}

com.java.FactoryMethod.Entity.LDPepperPizza
package com.java.FactoryMethod.Entity;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Entity
 * @className: LDPepperPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 19:59
 * @version: 1.0
 */
public class LDPepperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("伦敦的胡椒pizza");
        System.out.println("伦敦的胡椒pizza 正在准备原材料");
    }
}


com.java.FactoryMethod.Factory包
com.java.FactoryMethod.Factory.OrderPizza(抽象类)
package com.java.FactoryMethod.Factory;

import com.java.FactoryMethod.Entity.Pizza;

import java.util.Scanner;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Factory
 * @className: OrderPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 20:00
 * @version: 1.0
 */

public abstract class OrderPizza {

    //定义一个抽象方法,createPizza , 让各个工厂子类自己实现
    abstract Pizza createPizza(String orderType);

    // 构造器
    public OrderPizza() {
        Pizza pizza = null;
        String orderType; // 订购披萨的类型
//        do {
            orderType = getType();
            pizza = createPizza(orderType); //抽象方法,由工厂子类完成
            //输出pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
            pizza.finish();

//        } while (true);
    }



    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            Scanner input =new Scanner(System.in);
            System.out.print("请输入pizza的种类(cheese,pepper):");
            String str = input.nextLine();
            return str;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

}

com.java.FactoryMethod.Factory.BJOrderPizza
package com.java.FactoryMethod.Factory;

import com.java.FactoryMethod.Entity.BJCheesePizza;
import com.java.FactoryMethod.Entity.BJPepperPizza;
import com.java.FactoryMethod.Entity.Pizza;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Factory
 * @className: BJOrderPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 20:00
 * @version: 1.0
 */
public class BJOrderPizza extends OrderPizza {


    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

com.java.FactoryMethod.Factory.LDOrderPizza
package com.java.FactoryMethod.Factory;

import com.java.FactoryMethod.Entity.LDCheesePizza;
import com.java.FactoryMethod.Entity.LDPepperPizza;
import com.java.FactoryMethod.Entity.Pizza;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.Factory
 * @className: LDOrderPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 20:00
 * @version: 1.0
 */
public class LDOrderPizza extends OrderPizza {


    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

com.java.FactoryMethod.test包
com.java.FactoryMethod.test.PizzaStore(测试类)
package com.java.FactoryMethod.test;

import com.java.AbsFactory.Factory.AbsFactory;
import com.java.FactoryMethod.Factory.BJOrderPizza;
import com.java.FactoryMethod.Factory.LDOrderPizza;
import com.java.FactoryMethod.Factory.OrderPizza;

import java.io.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * @projectName:  
 * @package: com.java.FactoryMethod.test
 * @className: PizzaStore
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 20:00
 * @version: 1.0
 */
public class PizzaStore {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        while (true){
            try {
                Scanner input =new Scanner(System.in);
                System.out.print("请输入pizza的产地(BJ , LD)(exit退出):");
                String loc = input.nextLine();

//            if (loc.equals("BJ")) {
//                //创建北京口味的各种Pizza
//                new BJOrderPizza();
//            } else if (loc.equals("LD")){
//                //创建伦敦口味的各种Pizza
//                new LDOrderPizza();
//            }
//            else if (loc.equals("exit"))break;
//            else {
//                System.out.println("产地输入有误");
//            }


                // 利用“反射技术+读取配置文件”的方法对上述程序做改进;
                if (loc.equals("exit")) break;
                Properties properties = new Properties();
                InputStream is = new FileInputStream(new File("src/com/java/FactoryMethod/pizza.properties"));
                properties.load(is);
                is.close();
                String className = properties.getProperty(loc);
                OrderPizza factory = (OrderPizza) Class.forName(className).newInstance();


            }catch (Exception e){
                System.out.println("产地或种类输入错误!请重新输入...");
            }

        }

    }

}

配置文件
com/java/FactoryMethod/pizza.properties
BJ=com.java.FactoryMethod.Factory.BJOrderPizza
LD=com.java.FactoryMethod.Factory.LDOrderPizza

② 抽象工厂模式参考代码

com.java.AbsFactory.Entity包
com.java.AbsFactory.Entity.Pizza(抽象类)
package com.java.AbsFactory.Entity;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Entity
 * @className: Pizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:04
 * @version: 1.0
 */
//将Pizza 类做成抽象
public abstract class Pizza {
    protected String name; //名字

    //准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
    public abstract void prepare();


    public void bake() {
        System.out.println(name + " baking;");
    }

    public void cut() {
        System.out.println(name + " cutting;");
    }

    //打包
    public void box() {
        System.out.println(name + " boxing;");
    }

    public void setName(String name) {
        this.name = name;
    }
}

com.java.AbsFactory.Entity.BJCheesePizza
package com.java.AbsFactory.Entity;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Entity
 * @className: BJCheesePizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:04
 * @version: 1.0
 */
public class BJCheesePizza extends Pizza {

    @Override
    public void prepare() {
        setName("北京的奶酪pizza");
        System.out.println("北京的奶酪pizza 准备原材料");
    }

}

com.java.AbsFactory.Entity.BJPepperPizza
package com.java.AbsFactory.Entity;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Entity
 * @className: BJPepperPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:05
 * @version: 1.0
 */
public class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京的胡椒pizza");
        System.out.println("北京的胡椒pizza 准备原材料");
    }
}

com.java.AbsFactory.Entity.LDCheesePizza
package com.java.AbsFactory.Entity;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Entity
 * @className: LDCheesePizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:05
 * @version: 1.0
 */
public class LDCheesePizza extends Pizza{

    @Override
    public void prepare() {
        setName("伦敦的奶酪pizza");
        System.out.println("伦敦的奶酪pizza 准备原材料");
    }
}

com.java.AbsFactory.Entity.LDPepperPizza
package com.java.AbsFactory.Entity;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Entity
 * @className: LDPepperPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:05
 * @version: 1.0
 */
public class LDPepperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("伦敦的胡椒pizza");
        System.out.println("伦敦的胡椒pizza 准备原材料");
    }
}

com.java.AbsFactory.Factory包
com.java.AbsFactory.Factory.AbsFactory(interface类型)
package com.java.AbsFactory.Factory;

import com.java.AbsFactory.Entity.Pizza;

//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //让下面的工厂子类来 具体实现
    public Pizza createPizza(String orderType);
}

com.java.AbsFactory.Factory.BJFactory
package com.java.AbsFactory.Factory;

import com.java.AbsFactory.Entity.BJCheesePizza;
import com.java.AbsFactory.Entity.BJPepperPizza;
import com.java.AbsFactory.Entity.Pizza;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Factory
 * @className: BJFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:05
 * @version: 1.0
 */
//这是工厂子类
public class BJFactory implements AbsFactory {

    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("===使用的是抽象工厂模式===");
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")){
            pizza = new BJPepperPizza();
        }
        return pizza;
    }

}

com.java.AbsFactory.Factory.LDFactory
package com.java.AbsFactory.Factory;

import com.java.AbsFactory.Entity.LDCheesePizza;
import com.java.AbsFactory.Entity.LDPepperPizza;
import com.java.AbsFactory.Entity.Pizza;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Factory
 * @className: LDFactory
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:06
 * @version: 1.0
 */
public class LDFactory implements AbsFactory {

    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("===使用的是抽象工厂模式===");
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }

}

com.java.AbsFactory.Factory.OrderPizza
package com.java.AbsFactory.Factory;

import com.java.AbsFactory.Entity.Pizza;

import java.util.Scanner;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.Factory
 * @className: OrderPizza
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:07
 * @version: 1.0
 */
public class OrderPizza {

    AbsFactory factory;

    // 构造器
    public OrderPizza(AbsFactory factory) {
        setFactory(factory);
    }

    private void setFactory(AbsFactory factory) {
        Pizza pizza = null;
        String orderType = ""; // 用户输入
        this.factory = factory;
//        do {
            orderType = getType();
            // factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = factory.createPizza(orderType);
            if (pizza != null) { // 订购ok
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购失败");
//                break;
            }
//        } while (true);
    }

    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            Scanner input =new Scanner(System.in);
            System.out.print("请输入pizza的种类(cheese,pepper):");
            String str = input.nextLine();
            return str;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

com.java.AbsFactory.test包
com.java.AbsFactory.test.PizzaStore(测试类)
package com.java.AbsFactory.test;

import com.java.AbsFactory.Factory.AbsFactory;
import com.java.AbsFactory.Factory.BJFactory;
import com.java.AbsFactory.Factory.LDFactory;
import com.java.AbsFactory.Factory.OrderPizza;
import com.java.FactoryMethod.Factory.BJOrderPizza;
import com.java.FactoryMethod.Factory.LDOrderPizza;

import java.io.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * @projectName:  
 * @package: com.java.AbsFactory.test
 * @className: PizzaStore
 * @author: GCT
 * @description: TODO
 * @date: 2022/9/23 21:05
 * @version: 1.0
 */
public class PizzaStore {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        // TODO Auto-generated method stub
        //new OrderPizza(new BJFactory());
//        new OrderPizza(new LDFactory());

        while (true){
            try{
                Scanner input =new Scanner(System.in);
                System.out.print("请输入pizza的产地(BJ , LD)(exit退出):");
                String loc = input.nextLine();

//            if (loc.equals("BJ")) {
//                //创建北京口味的各种Pizza
//                new OrderPizza(new BJFactory());
//            } else if (loc.equals("LD")){
//                //创建伦敦口味的各种Pizza
//                new OrderPizza(new LDFactory());
//            }
//            else if (loc.equals("exit"))break;
//            else {
//                System.out.println("产地输入有误");
//            }

//            利用“反射技术+读取配置文件”的方法对上述程序做改进;
                if (loc.equals("exit")) break;
                Properties properties = new Properties();
                InputStream is = new FileInputStream(new File("src/com/java/AbsFactory/pizza.properties"));
                properties.load(is);
                is.close();
                String className = properties.getProperty(loc);
                AbsFactory factory = (AbsFactory) Class.forName(className).newInstance();
                new OrderPizza(factory);
            }catch (Exception e){
                System.out.println("产地或种类输入错误!请重新输入...");
            }
        }
    }
}

配置文件

com/java/AbsFactory/pizza.properties

BJ=com.java.AbsFactory.Factory.BJFactory
LD=com.java.AbsFactory.Factory.LDFactory

项目结构

在这里插入图片描述

运行结果

在这里插入图片描述

运行结果

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GCTTTTTT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值