• Java学习 --- 设计模式的工厂模式


    目录

    一、问题需求

    二、工厂模式

    2.1、简单工厂模式

    2.2、工厂方法模式

    2.3、抽象工厂模式

    五、工厂模式源码分析

     六、工厂模式总结


    一、问题需求

    需求:完成对披萨种类的扩展,便于维护。

    1、披萨的种类

    2、披萨制作的步骤

    3、披萨店的订购功能

    示例参考代码:

    1. //将Pizza类做成抽象类
    2. public abstract class Pizza {
    3. protected String name; //披萨名
    4. public abstract void prepare(); //披萨原材料
    5. public void bake(){
    6. System.out.println(name + "baking");
    7. }
    8. public void cut(){
    9. System.out.println(name + "cutting");
    10. }
    11. public void box(){
    12. System.out.println(name + "boxing");
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. }
    1. public class GreekPizza extends Pizza {
    2. @Override
    3. public void prepare() {
    4. System.out.println("准备制作希腊披萨的原材料");
    5. }
    6. }
    1. public class CheesePizza extends Pizza {
    2. @Override
    3. public void prepare() {
    4. System.out.println("准备制作奶酪披萨的原材料");
    5. }
    6. }
    1. import java.io.BufferedReader;
    2. import java.io.InputStreamReader;
    3. public class OrderPizza {
    4. //订购披萨的类型
    5. public OrderPizza() {
    6. Pizza pizza = null;
    7. String orderType;
    8. do {
    9. orderType = getType();
    10. if (orderType.equals("greek")){
    11. pizza = new GreekPizza();
    12. pizza.setName("希腊披萨");
    13. } else if (orderType.equals("cheese")){
    14. pizza = new CheesePizza();
    15. pizza.setName("奶酪披萨");
    16. } else {
    17. break;
    18. }
    19. //打印披萨制作过程
    20. pizza.prepare();
    21. pizza.bake();
    22. pizza.cut();
    23. pizza.box();
    24. } while (true);
    25. }
    26. public String getType(){
    27. try {
    28. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    29. System.out.println("请输入要订购的披萨:");
    30. String str = bufferedReader.readLine();
    31. return str;
    32. }catch (Exception e){
    33. e.printStackTrace();
    34. return "";
    35. }
    36. }
    37. }
    1. public class PizzaStore {
    2. public static void main(String[] args) {
    3. new OrderPizza();
    4. }
    5. }

    上述代码分析:

    1、简单、好操作、容易理解

    2、违反了设计模式的ocp原则,对扩展开放,对修改关闭,当给类增加新功能的时候,尽量不修改代码。

    3、使用简单工厂模式把创建Pizza对象封装到一个类中,这样我们就有新的Pizza种类时,只需要修改该类就行,其它创建到Pizza对象的代码就不需要修改

    二、工厂模式

    2.1、简单工厂模式

    1、简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。

    2、简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为。

    3、当在开发中会大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

    示例参考代码:

    1. //简单工厂模式
    2. public class SimpleFactory {
    3. private Pizza pizza;
    4. public Pizza createPizza(String orderType){
    5. pizza = null;
    6. if (orderType.equals("greek")){
    7. pizza = new GreekPizza();
    8. pizza.setName("希腊披萨");
    9. } else if (orderType.equals("cheese")){
    10. pizza = new CheesePizza();
    11. pizza.setName("奶酪披萨");
    12. }
    13. return pizza;
    14. }
    15. }
    1. public class OrderPizza {
    2. private SimpleFactory simpleFactory;
    3. private Pizza pizza;
    4. //构造器
    5. public OrderPizza(SimpleFactory simpleFactory) {
    6. setSimpleFactory(simpleFactory);
    7. }
    8. public void setSimpleFactory(SimpleFactory simpleFactory) {
    9. this.simpleFactory = simpleFactory; //设置简单工厂对象
    10. do {
    11. String orderType = "";
    12. orderType = getType();
    13. pizza = this.simpleFactory.createPizza(orderType);
    14. if (pizza != null){
    15. pizza.prepare();
    16. pizza.bake();
    17. pizza.cut();
    18. pizza.box();
    19. } else {
    20. break;
    21. }
    22. }while (true);
    23. }
    24. //用户输入要订购的披萨
    25. public String getType(){
    26. try {
    27. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    28. System.out.println("请输入要订购的披萨:");
    29. String str = bufferedReader.readLine();
    30. return str;
    31. }catch (Exception e){
    32. e.printStackTrace();
    33. return "";
    34. }
    35. }
    36. }
    1. public class PizzaStore {
    2. public static void main(String[] args) {
    3. new OrderPizza(new SimpleFactory());
    4. }
    5. }

    简单工厂模式又称静态工厂模式

    示例参考代码:

    1. //静态工厂模式
    2. public class SimpleFactory {
    3. public static Pizza createPizza(String orderType){
    4. Pizza pizza = null;
    5. if (orderType.equals("greek")){
    6. pizza = new GreekPizza();
    7. pizza.setName("希腊披萨");
    8. } else if (orderType.equals("cheese")){
    9. pizza = new CheesePizza();
    10. pizza.setName("奶酪披萨");
    11. }
    12. return pizza;
    13. }
    14. }
    1. public class OrderPizza {
    2. private Pizza pizza;
    3. //构造器
    4. public OrderPizza() {
    5. do {
    6. String orderType = "";
    7. orderType = getType();
    8. pizza = SimpleFactory.createPizza(orderType);
    9. if (pizza != null){
    10. pizza.prepare();
    11. pizza.bake();
    12. pizza.cut();
    13. pizza.box();
    14. } else {
    15. break;
    16. }
    17. }while (true);
    18. }
    19. //用户输入要订购的披萨
    20. public String getType(){
    21. try {
    22. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    23. System.out.println("请输入要订购的披萨:");
    24. String str = bufferedReader.readLine();
    25. return str;
    26. }catch (Exception e){
    27. e.printStackTrace();
    28. return "";
    29. }
    30. }
    31. }

    2.2、工厂方法模式

    需求:客户在点披萨时,可以点不同口味的披萨,如北京的芝士披萨,南京的奥尔良披萨等。

    问题:使用简单工厂模式,创建不同的简单工厂类,但是不利于软件的可维护性、可扩展性。

    解决方案:将项目的实例化功能抽象成抽象方法,在不同的点餐中由子类实现。

    工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

    示例参考代码:

    1. public abstract class OrderPizza {
    2. private Pizza pizza;
    3. //构造器
    4. public OrderPizza() {
    5. String orderType = "";
    6. do {
    7. orderType = getType();
    8. pizza = createPizza(orderType); //由工厂子类来完成
    9. if (pizza != null){
    10. pizza.prepare();
    11. pizza.bake();
    12. pizza.cut();
    13. pizza.box();
    14. } else {
    15. break;
    16. }
    17. }while (true);
    18. }
    19. //定义一个抽象方法,由各个工厂子类来实现。
    20. abstract Pizza createPizza(String orderType);
    21. //用户输入要订购的披萨
    22. public String getType(){
    23. try {
    24. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    25. System.out.println("请输入要订购的披萨:");
    26. String str = bufferedReader.readLine();
    27. return str;
    28. }catch (Exception e){
    29. e.printStackTrace();
    30. return "";
    31. }
    32. }
    33. }
    1. public class CDCheesePizza extends Pizza {
    2. @Override
    3. public void prepare() {
    4. setName("成都奶酪披萨");
    5. System.out.println("准备成都的奶酪披萨原材料");
    6. }
    7. }
    1. public class CDPepperPizza extends Pizza {
    2. @Override
    3. public void prepare() {
    4. setName("成都pepper披萨");
    5. System.out.println("准备杭州的pepper披萨原材料");
    6. }
    7. }
    1. public class CDOrderPizza extends OrderPizza {
    2. @Override
    3. Pizza createPizza(String orderType) {
    4. Pizza pizza = null;
    5. if (orderType.equals("cheese")){
    6. pizza = new CDCheesePizza();
    7. } else if (orderType.equals("pepper")){
    8. pizza = new CDPepperPizza();
    9. }
    10. return pizza;
    11. }
    12. }
    1. public class PizzaStore {
    2. public static void main(String[] args) {
    3. new CDOrderPizza();
    4. }
    5. }

    2.3、抽象工厂模式

    1、定义一个接口用于创建相关或有依赖关系的对象簇,而无需指明具体的类。

    2、抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合

    3、从设计层面看,抽象工厂模式就是对简单工厂模式的改进。

    4、将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类,我们可以根据创建对象类型使用对应的工厂子类。将单个的简单工厂类变为工厂簇,便于代码的维护和扩展。

    示例参考代码:

    1. //抽象工厂模式(抽象层)
    2. public interface AbsFactory {
    3. public Pizza createPizza(String orderType);
    4. }
    1. //工厂子类
    2. public class CDFactory implements AbsFactory {
    3. @Override
    4. public Pizza createPizza(String orderType) {
    5. Pizza pizza = null;
    6. if (orderType.equals("cheese")){
    7. pizza = new CDCheesePizza();
    8. } else if (orderType.equals("pepper")){
    9. pizza = new CDPepperPizza();
    10. }
    11. return pizza;
    12. }
    13. }
    1. public class OrderPizza {
    2. AbsFactory factory;
    3. public OrderPizza(AbsFactory factory) {
    4. setFactory(factory);
    5. }
    6. private void setFactory(AbsFactory factory) {
    7. Pizza pizza;
    8. String orderType = "";
    9. this.factory = factory;
    10. do {
    11. orderType = getType();
    12. pizza = factory.createPizza(orderType);
    13. if (pizza != null){
    14. pizza.prepare();
    15. pizza.bake();
    16. pizza.cut();
    17. pizza.box();
    18. } else {
    19. break;
    20. }
    21. }while (true);
    22. }
    23. //用户输入要订购的披萨
    24. public String getType(){
    25. try {
    26. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    27. System.out.println("请输入要订购的披萨:");
    28. String str = bufferedReader.readLine();
    29. return str;
    30. }catch (Exception e){
    31. e.printStackTrace();
    32. return "";
    33. }
    34. }
    35. }
    1. public class PizzaStore {
    2. public static void main(String[] args) {
    3. new OrderPizza(new CDFactory());
    4. }
    5. }

    五、工厂模式源码分析

    在JDK的Calender类:

    示例参考代码:

    1. public class Factory {
    2. public static void main(String[] args) {
    3. Calendar calendar = Calendar.getInstance();
    4. System.out.println("calendar.get(Calendar.YEAR) = " + calendar.get(Calendar.YEAR));
    5. System.out.println("calendar.get(Calendar.MONTH) = " + (calendar.get(Calendar.MONTH) + 1));
    6. System.out.println("calendar.get(Calendar.DAY_OF_MONTH) = " + calendar.get(Calendar.DAY_OF_MONTH));
    7. System.out.println("calendar.get(Calendar.HOUR_OF_DAY) = " + calendar.get(Calendar.HOUR_OF_DAY));
    8. System.out.println("calendar.get(Calendar.MINUTE) = " + calendar.get(Calendar.MINUTE));
    9. System.out.println("calendar.get(Calendar.SECOND) = " + calendar.get(Calendar.SECOND));
    10. }
    11. }

    第一步:

     第二步:

     第三步:

     

     六、工厂模式总结

    1、工厂模式的意义:将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦,从而提高项目的扩展性和维护性。

    2、设计模式依赖抽象的原则

    ①、创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂方法中,并返回,变量不要持有具体类的引用。

    ②、不要让类继承具体类,而是继承抽象类或者实现接口。

    ③、不要覆盖基类中已经实现的方法。

  • 相关阅读:
    「SpringCloud Alibaba」Sentinel实现熔断与限流
    如何处理海量数据文件以及大文件数据查找
    Redis持久化机制分析
    FPGA 安装Quartus 13.1无法生成.sof文件
    mipi介绍
    技术对接76
    其他word转化为PDF的方式
    【自然语言处理】【实体匹配】CollaborER:使用多特征协作的自监督实体匹配框架
    重制版 day 11函数基础
    《UnityShader入门精要》学习2
  • 原文地址:https://blog.csdn.net/qq_46093575/article/details/126070350