其他分享
首页 > 其他分享> > 工厂模式相关简单论述

工厂模式相关简单论述

作者:互联网

工厂模式相关简单论述

1.工厂模式简介

工厂模式用于对象的创建,使得客户从具体的产品对象中被解耦。

2.工厂模式的定义

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

3.工厂模式使用实例

我们现在先假设一个简单的需求:计算器


我们的第一版代码如下


import java.util.Scanner;

public class jisuanqi {
    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("the value of a");
            double a = scanner.nextInt();
            System.out.println("the value of b");
            double b = scanner.nextInt();
            System.out.println("+,-,*,/");
            String value = scanner.next();
            if ("+".equalsIgnoreCase(value)) {
                System.out.println(a + b);
            } else if ("-".equalsIgnoreCase(value)) {
                System.out.println(a - b);
            } else if ("*".equalsIgnoreCase(value)) {
                System.out.println(a * b);
            } else if ("/".equalsIgnoreCase(value) && b != 0 && a != 0) {
                System.out.println(a / b);
            } else {
                System.out.println("error");
            }
        } catch (Exception e) {
            System.out.println("error value");
        }

    }
}

我们上述代码中有两个初学者常见的代码习惯:

  1. 命名规范问题

  2. 大量的if代码

ok,那么我们对上述代码进行修改


我们的第二版代码如下


import java.util.Scanner;

public class jisuanqi {
    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("the OperateVlaue of a");
            double FirstOperateVlaue = scanner.nextInt();
            System.out.println("the OperateVlaue of b");
            double SecondOperateVlaue = scanner.nextInt();
            System.out.println("+,-,*,/");
            String operateValue = scanner.next();
            switch (operateValue){
                case "+":{
                    System.out.println(FirstOperateVlaue+SecondOperateVlaue);
                    break;
                }
                case "-":{
                    System.out.println(FirstOperateVlaue - SecondOperateVlaue);
                    break;
                }
                case "*":{
                    System.out.println(FirstOperateVlaue * SecondOperateVlaue);
                    break;
                }
                case "/":{
                    if (FirstOperateVlaue != 0 && SecondOperateVlaue!=0) {
                        System.out.println(FirstOperateVlaue / SecondOperateVlaue);
                        break;
                    }
                }
                default:{
                    System.out.println("error");
                    break;
                }

            }
        } catch (Exception e) {
            System.out.println("error OperateVlaue");
            e.printStackTrace();
        }

    }
}

但是现在又有一个问题:

  1. 这么多代码是不是显得很臃肿呢,我们维护和读代码时候也不好,我们应该怎么做呢

面向对象的方法解决问题便可以解决这个问题


我们的第三版的代码如下


public class ExampleMine {
    public static final String Exception_FirstFailure = "error value";
}
public class OperateValue {
    public static final String ADD_VALUE="+";
    public static final String REDUCE_VALUE="-";
    public static final String MULTIPLICATION_VALUE="*";
    public static final String DIVISION_VALUE="/";
}


import java.util.Scanimport java.util.Scanner;

public class JiServlet {
    private double FirstOperateVlaue;
    private double SecondOperateVlaue;

    public double getFirstOperateVlaue() {
        return FirstOperateVlaue;
    }

    public void setFirstOperateVlaue(double firstOperateValue){
        FirstOperateVlaue = firstOperateValue;
    }

    public double getSecondOperateVlaue() {
        return SecondOperateVlaue;
    }

    public void setSecondOperateVlaue(double secondOperateValue){
        SecondOperateVlaue = secondOperateValue;
    }

    public void GetNumbers() throws  Exception {

        switch (operateValue){
            case OperateValue.ADD_VALUE:{
                System.out.println(getFirstOperateVlaue()+getSecondOperateVlaue());
                break;
            }
            case OperateValue.REDUCE_VALUE:{
                System.out.println(getFirstOperateVlaue() - getSecondOperateVlaue());
                break;
            }
            case OperateValue.MULTIPLICATION_VALUE:{
                System.out.println(getFirstOperateVlaue() * getSecondOperateVlaue());
                break;
            }
            case OperateValue.DIVISION_VALUE:{
                if (this.getFirstOperateVlaue() != 0 && this.getSecondOperateVlaue()!=0) {
                    System.out.println(FirstOperateVlaue / SecondOperateVlaue);
                    break;
                }
            }
            default:{
                System.out.println(ExampleMine.Exception_FirstFailure);
                break;
            }

        }
    }
}

import java.util.Scanner;

public class jisuanqi {
    public static void main(String[] args) {
        JiServlet jiServlet = new JiServlet();
        Scanner scanner= new Scanner(System.in);
        try {
            System.out.println("the FirstOperateVlaue of a");
            jiServlet.setFirstOperateVlaue(scanner.nextInt());
            System.out.println("the SecondOperateVlaue of b");
            jiServlet.setSecondOperateVlaue(scanner.nextInt());
            System.out.println("+,-,*,/");
            jiServlet.setOperateValue(scanner.next());
            jiServlet.GetNumbers();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我们的第三版代码仍然存在问题:

  1. 我们是否感觉 switch 语句太臃肿了呢,我们可不可以将他们拆成四个类呢

我们的第四版代码如下:

这里使用的是工厂模式,一个最简单的工厂模式,我们发现这与我们的多态的写法是不尽相同的在这里

public class ExampleMine {
 public static final String Exception_FirstFailure = "error value";
}
package Base;

import java.util.Scanner;

public abstract class JiServlet {
    private double FirstOperateVlaue;
    private double SecondOperateVlaue;

    public double getFirstOperateVlaue() {
        return FirstOperateVlaue;
    }

    public void setFirstOperateVlaue(double firstOperateValue){
        FirstOperateVlaue = firstOperateValue;
    }

    public double getSecondOperateVlaue() {
        return SecondOperateVlaue;
    }

    public void setSecondOperateVlaue(double secondOperateValue){
        SecondOperateVlaue = secondOperateValue;
    }

    public double GetNumber() throws Exception{
        return 0.00;
    }
}
package Base;

import tools.GETSMultiplicationValue;
import tools.GetAddValue;
import tools.GetDivisionValue;
import tools.GetReduceValue;

public class OperateCation {
    public JiServlet GetOperateCation(String operation) throws Exception {
        switch (operation){
            case OperateValue.ADD_VALUE:{
                return new GetAddValue();
            }
            case OperateValue.REDUCE_VALUE:{
                return new GetReduceValue();
            }
            case OperateValue.MULTIPLICATION_VALUE:{
                return new GETSMultiplicationValue();
            }
            case OperateValue.DIVISION_VALUE:{
                return new GetDivisionValue();
            }
            default:{
                throw new Exception(ExampleMine.Exception_FirstFailure);
            }
        }
    }
}
package Base;

public class OperateValue {
    public static final String ADD_VALUE="+";
    public static final String REDUCE_VALUE="-";
    public static final String MULTIPLICATION_VALUE="*";
    public static final String DIVISION_VALUE="/";
}
package tools;

import Base.JiServlet;

public class GetAddValue extends JiServlet {
    @Override
    public double GetNumber() {
        return this.getFirstOperateVlaue()+this.getSecondOperateVlaue();
    }
}
package tools;

import Base.ExampleMine;
import Base.JiServlet;

public class GetDivisionValue extends JiServlet {
    @Override
    public double GetNumber() throws Exception {
        if (this.getFirstOperateVlaue()!= 0 && this.getSecondOperateVlaue()!=0) {
            return this.getFirstOperateVlaue()/this.getSecondOperateVlaue();
        }else{
            throw new Exception(ExampleMine.Exception_FirstFailure);
        }
    }
}
package tools;

import Base.JiServlet;

public class GetReduceValue extends JiServlet {
    @Override
    public double GetNumber() {
        return this.getFirstOperateVlaue()-this.getSecondOperateVlaue();
    }
}
package tools;

import Base.JiServlet;

public class GETSMultiplicationValue extends JiServlet {
    @Override
    public double GetNumber() {
        return this.getFirstOperateVlaue()*this.getSecondOperateVlaue();
    }
}
import Base.JiServlet;
import Base.OperateCation;

public class issuance {
    public static void main(String[] args) throws Exception {
        OperateCation operateCation = new OperateCation();
        JiServlet jiServlet = operateCation.GetOperateCation("+");
        jiServlet.setFirstOperateVlaue(12.0);
        jiServlet.setSecondOperateVlaue(19.0);
        System.out.println(jiServlet.GetNumber());
    }
}

UML图如下
在这里插入图片描述

注意

简单工厂实际不能算作一种设计模式,它引入了创建者的概念,将实例化的代码从应用代码中抽离,在创建者类的静态方法中只处理创建对象的细节,后续创建的实例如需改变,只需改造创建者类即可,

但由于使用静态方法来获取对象,使其不能在运行期间通过不同方式去动态改变创建行为,因此存在一定局限性。

4.工厂方法模式

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类。

场景延伸:不同地区咖啡工厂受制于环境、原料等因素的影响,制造出的咖啡种类有限。中国咖啡工厂仅能制造卡布奇诺、拿铁,而美国咖啡工厂仅能制造美式咖啡、拿铁。

/** * 定义一个抽象的咖啡工厂 * @author Lsj
 */
public abstract class CoffeeFactory {

    /**     * 生产可制造的咖啡     * @return
     */
    public abstract Coffee[] createCoffee();

}


/** * 中国咖啡工厂 * @author Lsj
 * */
public class ChinaCoffeeFactory extends CoffeeFactory {

    @Override
    public Coffee[] createCoffee() {
        // TODO Auto-generated method stub
        return new Coffee[]{new Cappuccino(), new Latte()};
    }

}


/** * 美国咖啡工厂 * @author Lsj
 * */
public class AmericaCoffeeFactory extends CoffeeFactory {

    @Override
    public Coffee[] createCoffee() {
        // TODO Auto-generated method stub
        return new Coffee[]{new Americano(), new Latte()};
    }

}


/** * 工厂方法测试 * @author Lsj
 * */
public class FactoryMethodTest {

    static void print(Coffee[] c){
        for (Coffee coffee : c) {
            System.out.println(coffee.getName());
        }
    }

    public static void main(String[] args) {
        CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();
        Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();
        System.out.println("中国咖啡工厂可以生产的咖啡有:");
        print(chinaCoffees);
        CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
        Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();
        System.out.println("美国咖啡工厂可以生产的咖啡有:");
        print(americaCoffees);
    }
}

5. 抽象工厂

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料。

如果用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造工厂、碳酸饮料制造工厂),4个具体工厂实现。随着产品的增多,会导致类爆炸。

所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担创建者的责任,负责制造不同的产品。

/**
 * 抽象的饮料产品家族制造工厂
 * @author Lsj
 *
 */
public interface AbstractDrinksFactory {

    /**
     * 制造咖啡
     * @return
     */
    Coffee createCoffee();

    /**
     * 制造茶
     * @return
     */
    Tea createTea();

    /**
     * 制造碳酸饮料
     * @return
     */
    Sodas createSodas();
}


/**
 * 中国饮品工厂
 * 制造咖啡与茶
 * @author Lsj
 *
 */
public class ChinaDrinksFactory implements AbstractDrinksFactory {

    @Override
    public Coffee createCoffee() {
        // TODO Auto-generated method stub
        return new Latte();
    }

    @Override
    public Tea createTea() {
        // TODO Auto-generated method stub
        return new MilkTea();
    }

    @Override
    public Sodas createSodas() {
        // TODO Auto-generated method stub
        return null;
    }

}


/**
 * 美国饮品制造工厂
 * 制造咖啡和碳酸饮料
 * @author Lsj
 *
 */
public class AmericaDrinksFactory implements AbstractDrinksFactory {

    @Override
    public Coffee createCoffee() {
        // TODO Auto-generated method stub
        return new Latte();
    }

    @Override
    public Tea createTea() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Sodas createSodas() {
        // TODO Auto-generated method stub
        return new CocaCola();
    }

}


/**
 * 抽象工厂测试类
 * @author Lsj
 *
 */
public class AbstractFactoryTest {

    static void print(Drink drink){
        if(drink == null){
            System.out.println("产品:--" );
        }else{
            System.out.println("产品:" + drink.getName());
        }
    }

    public static void main(String[] args) {
        AbstractDrinksFactory chinaDrinksFactory = new ChinaDrinksFactory();
        Coffee coffee = chinaDrinksFactory.createCoffee();
        Tea tea = chinaDrinksFactory.createTea();
        Sodas sodas = chinaDrinksFactory.createSodas();
        System.out.println("中国饮品工厂有如下产品:");
        print(coffee);
        print(tea);
        print(sodas);

        AbstractDrinksFactory americaDrinksFactory = new AmericaDrinksFactory();
        coffee = americaDrinksFactory.createCoffee();
        tea = americaDrinksFactory.createTea();
        sodas = americaDrinksFactory.createSodas();
        System.out.println("美国饮品工厂有如下产品:");
        print(coffee);
        print(tea);
        print(sodas);
    }
}

6.总结

7.扩展问题

如果我们的if语句有很多呢,我们应该怎么去做呢

我们会在下篇文档中进行论述我们的策略模式

8.相关链接

对于继承和封装基础内容有不解内容的同学请参考以下文档

参考书籍

7.扩展问题

如果我们的if语句有很多呢,我们应该怎么去做呢

我们会在下篇文档中进行论述我们的策略模式

8.相关链接

对于继承和封装基础内容有不解内容的同学请参考以下文档

参考书籍

标签:System,模式,工厂,println,new,论述,public,out
来源: https://blog.csdn.net/qq_45205390/article/details/122847875