• 【创建型模式】工厂方法模式


    一、简单工厂模式

    1.1 简单工厂模式概述

            简单工厂模式又叫做静态工厂方法模式

    • 目的:定义一个用于创建对象的接口。
    • 实质:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

    • 简单工厂模式基本实现流程
    • 1.具体产品类:将需要创建的各种不同产品对象的相关代码封装到具体产品类中;
    • 2.抽象产品类:将具体产品类公共的代码进行抽象和提取后封装在一个抽象产品类中;
    • 3.工厂类:提供一个工厂类用于创建各种产品,在工厂中提供一个创建产品的工厂方法,该方法可以根据所传入参数的不同创建不同的具体产品对象。
    • 4.客户端:指需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。

            创建对象与适用对象

    • Java语言创建对象的几种方式
      • 1.用new关键字直接创建对象;
      • 2.通过反射机制创建对象;
      • 3.通过克隆方法创建对象;
      • 4.通过工厂类创建对象。
    • 将对象的创建与使用分离的其他好处
      • 1.防止用来实例化一个类的数据和代码在多个类中到处都是,可以将有关创建的知识搬移到一个工厂类中,解决代码重复、创建蔓延的问题;
      • 2.构造函数的名字都与类名相同,从构造函数和参数列表中大家很难里哦阿姐不同构造函数所构造的产品的差异->将对象的创建过程封装在工厂类中,可以提供一系列名字完全不同的工厂方法,每一个工厂方法对应一个构造函数,客户端可以以一种更加可读、易懂的方式来创建对象。
    • 何时不需要工厂?
      • 1.无须为系统中的每一个类都配备一个工厂类;
      • 2.如果一个类很简单,而且不存在太多变化,其构造过程也很简单,此时就无须为其提供工厂类,直接在使用之前实例化即可;
      • 3.否则会导致工厂泛滥,增加系统的复杂度。

            简单工厂模式的简化:将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中。

    • 简单工厂模式的优缺点
      • 优点
        • 1.实现了对象创建和使用的分离
        • 2.客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可
        • 3.通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
      • 缺点
        • 1.工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响
        • 2.增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度
        • 3.系统扩展困难,一旦添加新产品不得不修改工厂逻辑
        • 4.由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展
    • 适用环境
      • 1.工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂
      • 2.客户端只知道传入工厂类的参数,对于如何创建对象并不关心

     1.2 代码实现

            简单工厂模式包含3个角色:

    • 工厂角色
    • 抽象产品角色
    • 具体产品角色
            1.2.1 抽象产品角色(Pizza:将具体行为抽象出来)
    1. package factory.simple.pizzaFactory;
    2. //抽象产品
    3. import java.util.ArrayList;
    4. public abstract class Pizza {
    5. String name;
    6. String dough;//面团
    7. String sauce;//酱料
    8. ArrayList toppings=new ArrayList();//佐料
    9. public void prepare(){
    10. System.out.println("preparing "+ name);
    11. System.out.println("Tossing dough... ");
    12. System.out.println("adding sauce... ");
    13. for (int i=0;i
    14. System.out.println(" "+toppings.get(i));
    15. }
    16. public void bake(){
    17. System.out.println("Bake for 25minutes at 350"); }
    18. public void cut(){
    19. System.out.println("cutting the pizza"); }
    20. public void box(){
    21. System.out.println("place pizza in officical Pizza box");}
    22. public String getName(){
    23. return name;
    24. }
    25. }
            1.2.2 工厂角色(SimpleFactory:产生Pizza)
    1. package factory.simple.pizzaFactory;
    2. //工厂角色
    3. public class SimpleFactory {
    4. public Pizza createPizza(String type) {
    5. Pizza pizza = null;
    6. if (type.equals("cheese")) {
    7. pizza = new CheesePizza();
    8. } else if (type.equals("pepperoni")) {
    9. pizza = new PepperoniPizza();
    10. } else if (type.equals("Greek")) {
    11. pizza = new GreekPizza();
    12. } else if (type.equals("clam")) {
    13. pizza = new ClamPizza();
    14. } else if (type.equals("veggie")) {
    15. pizza = new VeggiePizza();
    16. }
    17. return pizza;
    18. }
    19. }
            1.2.3 具体产品角色(CheesePizza、ClamPizza、GreekPizza、PepperoniPizza、VeggiePizza)
    1. package factory.simple.pizzaFactory;
    2. //具体产品类
    3. public class CheesePizza extends Pizza {
    4. public void prepare(){
    5. System.out.println("Cheese比萨原材料正在准备中....");
    6. }
    7. public void bake(){
    8. System.out.println("Cheese比萨正在焙烤中....");
    9. }
    10. public void cut(){
    11. System.out.println("Cheese比萨,切块中....");
    12. }
    13. public void box(){
    14. System.out.println("Cheese比萨,正在打包....");
    15. }
    16. }
    1. package factory.simple.pizzaFactory;
    2. //具体产品类
    3. public class ClamPizza extends Pizza {
    4. public void prepare(){
    5. System.out.println("Clam比萨原材料正在准备中....");
    6. }
    7. public void bake(){
    8. System.out.println("Clam比萨正在焙烤中....");
    9. }
    10. public void cut(){
    11. System.out.println("Clam比萨,切块中....");
    12. }
    13. public void box(){
    14. System.out.println("Clam比萨,正在打包....");
    15. }
    16. }
    1. package factory.simple.pizzaFactory;
    2. //具体产品类
    3. public class GreekPizza extends Pizza {
    4. public void prepare(){
    5. System.out.println("Greek比萨原材料正在准备中....");
    6. }
    7. public void bake(){
    8. System.out.println("Greek比萨正在焙烤中....");
    9. }
    10. public void cut(){
    11. System.out.println("Greek比萨,切块中....");
    12. }
    13. public void box(){
    14. System.out.println("Greek比萨,正在打包....");
    15. }
    16. }
    1. package factory.simple.pizzaFactory;
    2. //具体产品类
    3. public class PepperoniPizza extends Pizza {
    4. public void prepare(){
    5. System.out.println("Pepperoni比萨原材料正在准备中....");
    6. }
    7. public void bake(){
    8. System.out.println("Pepperoni比萨正在焙烤中....");
    9. }
    10. public void cut(){
    11. System.out.println("Pepperoni比萨,切块中....");
    12. }
    13. public void box(){
    14. System.out.println("Pepperoni比萨,正在打包....");
    15. }
    16. }
    1. package factory.simple.pizzaFactory;
    2. //具体产品类
    3. public class VeggiePizza extends Pizza {
    4. public void prepare(){
    5. System.out.println("Veggie比萨原材料正在准备中....");
    6. }
    7. public void bake(){
    8. System.out.println("Veggie比萨正在焙烤中....");
    9. }
    10. public void cut(){
    11. System.out.println("Veggie比萨,切块中....");
    12. }
    13. public void box(){
    14. System.out.println("Veggie比萨,正在打包....");
    15. }
    16. }
            1.2.4 客户端类(PizzaStore:产生Pizza)
    1. package factory.simple.pizzaFactory;
    2. //客户端,取得Pizza
    3. public class PizzaStore {
    4. SimpleFactory sf;
    5. public PizzaStore(SimpleFactory sf) {
    6. super();
    7. this.sf = sf;
    8. }
    9. Pizza orderPizza(String name){
    10. Pizza pizza=sf.createPizza(name);
    11. pizza.prepare();
    12. pizza.bake();
    13. pizza.cut();
    14. pizza.box();
    15. return pizza;
    16. }
    17. }
            1.2.5 main方法实现简单工厂模式(Test)
    1. package factory.simple.pizzaFactory;
    2. import factory.simple.pizzaFactory.PizzaStore;
    3. public class Test {
    4. public static void main(String[] args) {
    5. // TODO Auto-generated method stub
    6. SimpleFactory sf=new SimpleFactory();//创建一个披萨工厂
    7. PizzaStore store=new PizzaStore(sf);//产生披萨制作商店
    8. store.orderPizza("cheese");//点餐
    9. }
    10. }
            1.2.6 UML图 

    1.3 代码结构

    二、工厂方法模式

    2.1 工厂方法模式概述

            工厂方法模式的定义-意图:一个用于创建对象的接口,让子类“决定”实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。“决定”并不是模式允许子类本身再运行时做决定,而是指再编写创建者类时,不需要知道实际创建的产品时哪一个。(类创建型模式)

            工厂方法模式简称工厂模式、虚拟构造器模式、多态工厂模式。其中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象目的是将产品类的实例化操作延迟到工厂类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

    • 工厂方法模式优缺点
      • 优点
        • 1.工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节;
        • 2.能够让工厂自主确定创建这个对象的细节则完全封装在具体工厂内部。3.在系统中加入新产品时,完全符合开闭原则。
      • 缺点
        • 1.系统中类的个数将成为对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销;
        • 2.增加了系统的抽象性和理解难度。
    • 适用环境
      • 1.客户端不知道它所需要的对象的类(客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建。)
      • 2.抽象工厂类通过其子类来指定创建哪个对象。

    2.2 代码实现

            工厂方法模式包含四个角色:

    • 抽象产品(Product):定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口;
    • 具体产品类(Concreteproduct):具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应;
    • 抽象工厂类(Factory):声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口;(类似工厂总部)
    • 具体工厂类(Concretefactory):抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。(类似各个子工厂)
            2.2.1 抽象产品类(Pizza)
    1. package factory.factorymethod.pizza;
    2. import java.util.ArrayList;
    3. //抽象产品类:披萨
    4. public abstract class Pizza {
    5. String name;
    6. String dough;//面团
    7. String sauce;//酱料
    8. //下行代码就是得到不同店的佐料制作方式
    9. ArrayList toppings=new ArrayList();//佐料
    10. public void prepare(){
    11. System.out.println("preparing "+ name);
    12. System.out.println("Tossing dough... ");
    13. System.out.println("adding sauce... ");
    14. //选择不同店的佐料制作方式
    15. for (int i=0;i
    16. System.out.println(" "+toppings.get(i));
    17. }
    18. public void bake(){
    19. System.out.println("Bake for 25minutes at 350"); }
    20. public void cut(){
    21. System.out.println("cutting the pizza"); }
    22. public void box(){
    23. System.out.println("place pizza in officical Pizza box");}
    24. public String getName(){
    25. return name;
    26. }
    27. }
            2.2.2 具体产品类(ChicagoCheesePizza、ChicagoPepperoniPizza、NYCheesePizza、NYPepperoniPizza)
    1. package factory.factorymethod.pizza;
    2. //具体产品类:芝加哥cheese披萨
    3. public class ChicagoCheesePizza extends Pizza {
    4. public ChicagoCheesePizza() {
    5. name="ChicagoCheesePizza";
    6. dough="Chicago style 面团";
    7. sauce="Chicago style 酱汁";
    8. toppings.add("NYCheesePizzaChicagoCheesePizza");
    9. }
    10. }
    1. package factory.factorymethod.pizza;
    2. //具体产品类:芝加哥Pepperoni披萨
    3. public class ChicagoPepperoniPizza extends Pizza {
    4. public ChicagoPepperoniPizza() {
    5. name="ChicagoPepperoniPizza";
    6. dough="Chicago style 面团";
    7. sauce="Chicago style 酱汁";
    8. toppings.add("Chicago style PepperoniPizza");
    9. }
    10. }
    1. package factory.factorymethod.pizza;
    2. //具体产品类:纽约Cheese披萨
    3. public class NYCheesePizza extends Pizza {
    4. public NYCheesePizza() {
    5. name="NYCheesePizza";
    6. dough="NY style 面团";
    7. sauce="NY style 酱汁";
    8. toppings.add("NYCheesePizza");
    9. }
    10. }
    1. package factory.factorymethod.pizza;
    2. //具体产品类:纽约Pepperoni披萨
    3. public class NYPepperoniPizza extends Pizza {
    4. public NYPepperoniPizza() {
    5. name="NYPepperoniPizza";
    6. dough="NY style 面团";
    7. sauce="NY style 酱汁";
    8. toppings.add("NYPepperoniPizza");
    9. }
    10. }
            2.2.3 抽象工厂类(PizzaStore)
    1. package factory.factorymethod.pizza;
    2. //抽象工厂类:披萨商店(总部)
    3. public abstract class PizzaStore {
    4. public final Pizza orderPizza(String name){
    5. // 把创建Pizza从工厂中移回来
    6. Pizza pizza=createPizza(name);
    7. pizza.prepare();
    8. pizza.bake();
    9. pizza.cut();
    10. pizza.box();
    11. return pizza;
    12. }
    13. public abstract Pizza createPizza(String name);
    14. }
            2.2.4 具体工厂类(ChicagoPizzaStore、NYPizzaStore)
    1. package factory.factorymethod.pizza;
    2. //具体工厂类:芝加哥披萨店
    3. public class ChicagoPizzaStore extends PizzaStore {
    4. @Override
    5. public Pizza createPizza(String name) {
    6. Pizza pizza=null;
    7. if(name.equals("cheese"))
    8. pizza=new ChicagoCheesePizza();
    9. else if(name.equals("pepperoni"))
    10. pizza=new ChicagoPepperoniPizza();
    11. return pizza;
    12. }
    13. }
    1. package factory.factorymethod.pizza;
    2. //具体工厂类:纽约披萨店
    3. public class NYPizzaStore extends PizzaStore {
    4. @Override
    5. public Pizza createPizza(String name) {
    6. Pizza pizza=null;
    7. if(name.equals("cheese"))
    8. pizza=new NYCheesePizza();
    9. else if(name.equals("pepperoni"))
    10. pizza=new NYPepperoniPizza();
    11. return pizza;
    12. }
    13. }
            2.2.5 main方法实现工厂方法模式(Test)
    1. package factory.factorymethod.pizza;
    2. public class Test {
    3. public static void main(String[] args) {
    4. NYPizzaStore ns=new NYPizzaStore();
    5. ns.orderPizza("cheese");
    6. ChicagoPizzaStore cs=new ChicagoPizzaStore();
    7. cs.orderPizza("cheese");
    8. }
    9. }
            2.2.6 UML图

    2.3 代码结构

  • 相关阅读:
    数位dp算法leetcode.788
    Go入门教程
    【每日一题】782. 变为棋盘
    计算机网络:运输层 - TCP 流量控制 & 拥塞控制
    晨曦记账本记账,如何自定义收支类别
    洛谷P2523 Problem c
    OpenCV图像处理(上)几何变换+形态学操作
    解析:去中心化托管解决方案概述
    Nestjs入门和环境搭建
    实现Loading倒影效果-webkit-box-reflect
  • 原文地址:https://blog.csdn.net/qq_45276194/article/details/137876698