欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《设计模式入门》 2.工厂方法模式

程序员文章站 2022-03-01 15:01:44
...

工厂方法模式(Factory Method Pattern)又称为工厂模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

简单来说就是我们不去直接生成对应的具体产品,而是把生产产品的功能交给工厂,我们只需要给工厂下订单就好了。

工厂方法模式一般分为四个部分:

抽象工厂(AbstractCreator)角色:担任这个角色的是工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须继承或者实现这个接口,在实际的系统中,这个角色常常有Java抽象类来实现。

具体工厂(ConcreteCreator)角色:担任这个角色的是实现了抽象工厂接口的具体Java类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。

抽象产品(AbstractProduct)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在实际应用中这个角色常常由Java的抽象类来实现。

具体产品(ConcreteProduct)角色:这个角色实现了抽象产品角色所声明的接口,工厂方法所创建的每一个对象都是某个具体产品角色的实例。

=========================================================================

还是生产手机的例子:

------------------------------------------------

        假设我们有工厂生产手机,我们有三种手机,分别是华为P50,小米12,还有苹果Iphone13 Pro Max。

        这时候我们来想,我们不直接去生产手机,而是把手机生产交给第三方代工厂,让他们来生产手机,这样我们只需要去对应相应的代工厂发订单,就可以生产相应的手机了,不需要知道代工厂的生产过程。

------------------------------------------------

抽象工厂角色

对应工厂的父类,有创建手机的功能 。

package FactoryMethodPattern.factories;

import Phones.Phone;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Factory.java
 * @Description 工厂的抽象类
 * @createTime 2022年02月10日 16:51:00
 */
public abstract class Factory {
    /**
     *创建对应的手机
     * @return 返回创建好对应的手机
     */
    public abstract Phone createPhone();
}

具体工厂角色

继承并且实现了具体的制造手机的方法,制造对应的手机 。

英华达代工小米

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Envada.java
 * @Description 小米代工厂
 * @createTime 2022年02月10日 16:59:00
 */
public class Envada extends Factory{
    @Override
    public Phone createPhone() {
        return new XiaoMi11U();
    }
}

伟创力代工华为

package FactoryMethodPattern.factories;

import Phones.HuaWeiP50;
import Phones.Phone;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Flex.java
 * @Description 华为代工厂
 * @createTime 2022年02月10日 17:00:00
 */
public class Flex extends Factory{
    @Override
    public Phone createPhone() {
        return new HuaWeiP50();
    }
}

富士康代工苹果

package FactoryMethodPattern.factories;

import Phones.IPhone13ProMax;
import Phones.Phone;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName FoxConn.java
 * @Description IPHONE代工厂
 * @createTime 2022年02月10日 16:57:00
 */
public class FoxConn extends Factory {

    @Override
    public Phone createPhone() {
        return new IPhone13ProMax();
    }
}

抽象产品角色

和简单工厂一样,对应代工产品的一个抽象

package Phones;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Phones.Phone.java
 * @Description 手机抽象方类,所有抽象方法在子类进行实现
 * @createTime 2022年02月08日 17:27:00
 */
public abstract class Phone {
    /**
     *打电话功能抽象方法
     */
    public abstract void call();
    /**
     *短信功能抽象方法
     */
    public abstract void message();
    /**
     *游戏功能抽象方法
     */
    public abstract void game();
}

具体产品角色

小米的实现类

package Phones;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName XiaoMi12.java
 * @Description Mi11U的实现类
 * @createTime 2022年02月08日 17:03:00
 */
public class XiaoMi11U extends Phone{

    public XiaoMi11U(){
        System.out.println("create XiaoMi11U");
    }

    @Override
    public void call() {
        System.out.println("da....da.....da....");
    }

    @Override
    public void message() {
        System.out.println("Message: Hello MIUI");
    }

    @Override
    public void game() {
        System.out.println("WIFI ERROR");
    }
}

华为的实现类

package Phones;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName MiPhone.java
 * @Description 华为的实现类
 * @createTime 2022年02月08日 17:02:00
 */
public class HuaWeiP50 extends Phone{
    public HuaWeiP50(){
        System.out.println("create HuaWeiP50");
    }

    @Override
    public void call() {
        System.out.println("di...di....di....");
    }

    @Override
    public void message() {
        System.out.println("Message: Hello Harmony");
    }

    @Override
    public void game() {
        System.out.println("WeGame Start");
    }
}

苹果的实现类

package Phones;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName IPhone.java
 * @Description Iphone 的实现类
 * @createTime 2022年02月08日 17:02:00
 */
public class IPhone13ProMax extends Phone {

    public IPhone13ProMax(){
        System.out.println("create iphone");
    }

    @Override
    public void call() {
        System.out.println("du....du....du....");
    }

    @Override
    public void message() {
        System.out.println("Imessage: Hello Iphone");
    }

    @Override
    public void game() {
        System.out.println("IGame Start");
    }
}

主函数:

        主函数下,我们不需要知道生产的过程和结果,我们需要做的只是给代工厂下订单,代工厂就可以制造对应的手机了

package FactoryMethodPattern;

import FactoryMethodPattern.factories.Envada;
import FactoryMethodPattern.factories.Factory;
import FactoryMethodPattern.factories.Flex;
import FactoryMethodPattern.factories.FoxConn;
import Phones.Phone;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName BuyPhone2.java
 * @Description 通过代工厂进行创建
 * @createTime 2022年02月10日 17:02:00
 */
public class BuyPhone2 {
    public static void main(String[] args) throws Exception {
        //输入代工厂
        String type = "FoxConn";
        Factory factory = getByFactory(type);
        Phone phone = factory.createPhone();
        phone.message();
    }

    public static Factory getByFactory(String type) throws Exception {
        if (!type.isEmpty()) {
            switch (type) {
                case "FoxConn":
                    return new FoxConn();
                case "Flex":
                    return new Flex();
                case "Envada":
                    return new Envada();
                default:
                    System.out.println("Create Error: Error Type");
                    throw new Exception();
            }
        } else {
            System.out.println("Create Error: No Type Identify");
            throw new Exception();
        }
    }
}

《设计模式入门》 2.工厂方法模式

 

模式优点 :

        在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
        基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
        使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

模式缺点 :

        在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
        由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。