创建多个“产品”的方式——工厂方法模式总结

简单工厂模式严格来说不算一个设计模式——缺点

继续说之前提到的简单工厂模式,严格来说,这不算一个设计模式……而且在业务量比较多了之后,它也有诸多的隐患

1、由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连

2、由于简单工厂模式的产品基于一个共同的抽象类或者接口,这样一来,产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,简单工厂类就需要维护大量的if-else判断,比如导入导出功能,虽然可以用反射或者配置文件,注解等解耦,但是还有更好的办法。

不使用工厂方法模式的例子

还是举那个水果的例子:之前水果园子里只有苹果和香蕉两种水果,现在又新加一个梨的品种。简单工厂类的代码如下:

// 简单工厂类
public class FruitFactoryA {
    public static FruitA getFruit(String type) {
        if ("apple".equalsIgnoreCase(type)) {
            return new AppleA();
        } else if ("banana".equalsIgnoreCase(type)) {
            return new BananaA();
        } else if ("pear".equalsIgnoreCase(type)) {
            return new PearA();
        } else {
            System.out.print("error!");
        }

        return null;
    }
}

该例子使用简单工厂模式,工厂类过于臃肿。

public class Main {
    public static void main(String[] args) {
        FruitA apple = FruitFactoryA.getFruit("apple");
        FruitA banana = FruitFactoryA.getFruit("banana");
        FruitA pear = FruitFactoryA.getFruit("pear");

        // 不太好,没有检测null异常,演示
        apple.get();
        banana.get();
        pear.get();
    }
}

因为简单工厂模式只有一个工厂类,它需要处理所有的对象创建的逻辑。如果日后需求不断增加,则后果不堪设想,违背了单一职责,导致系统丧失灵活性和可维护性。而且更重要的是,简单工厂模式违背了OCP——开放封闭原则。当然还有单一职责原则(虽然这里没具体体现)。那么如何改进呢?

引入工厂方法模式——让子类去创建对象

如何才能实现工厂类的代码不去修改,而开放扩展——可以把工厂的职责抽象,抽象if-else判断逻辑,把每一个判断都抽象为一个工厂类,而这些具体的工厂类统一抽象为一个接口来约束具体子类去生产产品,这就是传说中的——工厂方法模式,它同样属于类的创建型模式,又被称为多态工厂模式。

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口(仅仅起到一个约束生产动作的作用),这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

工厂方法模式实现

抽象工厂角色:工厂方法模式的核心,任何工厂类都必须实现这个接口

public interface FactoryA {
    FruitA getFruit();
}

具体工厂( Concrete  Creator)角色;具体工厂类是抽象工厂的一个实现,负责实例化产品对象

public class AppleFactoryA implements FactoryA {
    @Override
    public FruitA getFruit() {
        return new AppleA();
    }
}

public class BananaFactoryA implements FactoryA {
    @Override
    public FruitA getFruit() {
        return new BananaA();
    }
}

public class PearFactory implements FactoryA {
    @Override
    public FruitA getFruit() {
        return new PearA();
    }
}

抽象产品(Product)角色;工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口

public interface FruitA {
    void get();
}

具体产品(Concrete Product)角色;工厂方法模式所创建的具体实例对象

public class AppleA implements FruitA {
    @Override
    public void get() {
        System.out.println("苹果");
    }
}

public class BananaA implements FruitA {
    @Override
    public void get() {
        System.out.println("香蕉");
    }
}

public class PearA implements FruitA {
    @Override
    public void get() {
        System.out.println("梨");
    }
}

客户端调用

public class Main {
    public static void main(String[] args) {
        // 得到对应的水果的工厂
        FactoryA appleF = new AppleFactoryA();
        FactoryA bananaF = new BananaFactoryA();
        FactoryA peatF = new PearFactory();

        // 通过各个工厂去得到对应的水果
        FruitA apple = appleF.getFruit();
        FruitA banana = bananaF.getFruit();
        FruitA pear = peatF.getFruit();

        apple.get();
        banana.get();
        pear.get();
    }
}

如上代码,如果以后有新的水果出现,比如橘子,那么不用修改工厂类,只需要增加一个橘子以及橘子的工厂类,且橘子工厂同时去遵循工厂的接口即可,客户端调用就可以了,而其他已经写好的工厂类无需修改!完全符合OCP原则,同时每个具体工厂子类只负责对应水果的生成,也遵守了单一职责原则

类图如下

简单工厂和工厂方法模式对比

工厂方法模式与简单工厂模式在结构上的不同不是很明显。

1、工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

2、工厂方法模式之所以有一个别名叫多态性工厂模式,是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要任何修改,也不需要修改客户端原有的代码,很好的符合了“开放-封闭”原则。

而简单工厂在添加新产品对象后,不得不修改工厂方法,扩展性不好。

工厂方法模式退化后可以演变成简单工厂模式。

JDK 中的工厂方法模式

JAVA的 API 里使用了工厂方法模式的也很多很多,常用的比如,Object 类里的 toString() 方法,Java 的任何类,都可以继承或者覆写toString 方法,Object 相当于抽象工厂类,各个Java 的类,相当于具体工厂类。

还有 util 包里的Calendar类,该类是一个抽象类,它为特定瞬间与一组诸如 YEARMONTHDAY_OF_MONTHHOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
    public static Calendar getInstance() {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
}

该节选的代码片段有一个静态的 getInstance() 方法,return 了一个具体的日历对象,Calendar 是工厂方法模式里的抽象工厂类,而具体工厂子类(简单举几个例子)有JapaneseImperialCalendar,GregorianCalendar……

createCalendar 方法是 private 的,是属于 getInstance 方法里的,也就是说 Calendar 这个抽象工厂类返回具体子类的对象,JDK 里这样说:

与其他语言环境敏感类一样,Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。Calendar 的 getInstance 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化……

客户端通过该方法返回对应的日历工厂,客户端再通过这些日历工厂去生成对应的日历产品……将来如果需要支持某个其他地区的特殊历法,程序员除了必要的增加对应的日历工厂并 extends Calendar 这个抽象工厂,且增加对应的日历产品之外,只需要增加 Calendar 的 getInstance 方法的新的逻辑,但 Calendar 的使用者无需承担这种变化的影响,符合OCP。

原文地址:https://www.cnblogs.com/kubixuesheng/p/10344431.html

时间: 2024-10-04 13:39:44

创建多个“产品”的方式——工厂方法模式总结的相关文章

创建型设计模式(一)工厂方法模式

一.一句话背景 我需要一辆汽车,那我可以直接从工厂里面提货,而不用去管汽车是怎么做出来的,以及生产汽车的具体实现,我只需要告诉这个工厂要生产什么品牌的汽车就好,具体的汽车生产流水线我也不用管. 二.使用场景 知道部分特性而创建具体对象的场景. 如:根据环境类型(dev,test或master等)直接调用一整套环境配置 三.模型分析 生产流水线:接口,定义了生产汽车的方法 具体产品的生产流水线:类,里面的方法帮我们创建具体的类对象(汽车),生产流水线接口的具体实现 工厂:类,需要根据客户需求调用不

JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)

简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实现添加新产品而不影响已有代码?工厂方法模式应运而生,本文将介绍另外一种工厂模式--工厂方法模式. 1 日志记录器的设计 Sunny软件公司欲开发一个系统执行日志记录器(Logger).该记录器能够通过多种途径保存系统的执行日志,如通过文件记录或数据库记录,用户能够通过改动配置文件灵活地更换日志记录方式. 在设

创建模式之工厂方法模式

视频录制地址:https://www.bilibili.com/video/BV1s7411X7cJ/  (https://member.bilibili.com/v2#/upload-manager/article) (因为视频暂时还在审核.所以提供后台地址) 一.简单工厂模式简述 简单工厂模式定义如下: 简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创 建的实例通常都具有共同的父类.因为在简单工厂模式中用于创建实例的方法

工厂方法模式概述

工厂方法模式概述 在简单工厂模式中只提供一个工厂类,该工厂类处于对产品类进行实例化的中心位置,它需要知道每一个产品对象的创建细节,并决定何时实例化哪一个产品类.简单工厂模式最大的缺点是当有新产品要加入到系统中时,必须修改工厂类,需要在其中加入必要的业务逻辑,这违背了“开闭原则”.此外,在简单工厂模式中,所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题. 在工厂方法模式中,我们不再

php设计模式 — 工厂方法模式(多态性工厂模式) (虚拟构造子模式)

概念介绍: 工厂方法模式: 在学习工厂方法模式之前请首先阅读简单工厂模式工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中.工厂方法模式是简单工厂模式的进一步抽象和推广 工厂方法模式的几个需要的对象: 1.抽象工厂 2.具体工厂:实现抽象工厂接口列出的方法,并且每个工厂对应各自的产品 3.抽象产品 4.具体产品 工厂方法模式里面的果园的例子,可以改写成工厂方法模式 , 大家可以自己实验. 案例图: 代码实例: 1 <?php 2 3 //此实例是根据女娲造人写的 4

深入浅出设计模式——工厂方法模式(Factory Method)

介绍在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计模式的创建型设计模式.它解决的仍然是软件设计中与创建对象有关的问题.它可以更好的处理客户的需求变化. 引入我们继续来说"new"的问题,我们在简单工厂模式中,将实例化对象的工作推迟到了专门负责创建对象的工厂类中,这样,在我们事先预知的情况下,可以根据我们的需要动态创建产品类.但是,我们的预知是有限的,客户的变化可能是无限的.所以,就出现了问题,一旦客户的变化超越了我们的预知,我们就必须修改我们的

设计模式三:工厂方法模式

疑惑解答: 1.interface接口不能够实例化(new),但是可以定义引用来指向继承该接口的实体类: 如: interface animal{ void eat(); } class Cat implements animal{ public void eat(){ System.out.println("The cat eat!"); } } animal an = new Cat(); 一.什么是工厂方法模式 1.是简单工厂模式的进一步抽象: 2.定义一个创建产品对象的工厂接口

设计模式—工厂方法模式

工厂方法模式又叫多态性工厂(Polymorphic Factory)模式,工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中. 那么工厂方法模式是在什么场景下使用呢,下面就以本人的理解举例说明: 相信很多人都做过导入导出功能,就拿导出功能来说.有这么一个需求:XX系统需要支持对数据库中的员工薪资进行导出,并且支持多种格式如:HTML.CSV.PDF等,每种格式导出的结构有所不同,比如:财务跟其他人对导出薪资的HTML格式要求可能会不一样,因为财务可能需要特定的格式方便

Java设计模式之工厂方法模式

工厂方法模式介绍 有时候,由于产品的多样化,但是产品的功能却有某种共同的联系.我们希望定义一个用于创建产品对象的公共接口,让子类决定去如何实现这个功能.然后,我们定义一个生产产品的"工厂",所有的产品将从这个工厂里面生产出来,这样我们就使得产品的构造的细节与工厂分离了,这样产品的实现细节就被封装起来了,并且产品的可扩展性也很强.那么,这种设计模式我们称为工厂方法模式.具体的实例有很多,比如说去年的某一阵子脸萌软件爆红,其中就运用到了工厂方法模式来给用户生产各种脸型. 工厂方法模式分类