简单工厂模式

原文链接:简单工厂模式 | 偷掉月亮 (moonshuo.cn)

概述

定义一个工厂类,它可以根据参数的不同的返回不同类的实例,被创建的实例具有共同的父类。

代码举例

比如我们要求工厂提供水果,我们不需要关心工厂的水果如何创建出来,只是关心我们给出水果的名称,工厂能否得到对应的水果。

package 设计模式.简单工厂模式.example1;

/**
 * @author 21050
 * @date 2022-07-25 19:59:06
 * @description  所有水果的父类
 */
public abstract class Fruit {
    protected String fruitName;
    /**水果的生长方式不同*/
    public abstract void growingFruit();
    /**假设水果的运输方式相同*/
    public void  transportation(){
        System.out.println("开始运输"+fruitName+"到工厂");
    }

    public Fruit(String fruitName) {
        this.fruitName = fruitName;
    }
}

工厂

package 设计模式.简单工厂模式.example1;

/**
 * @author 21050
 * @date 2022-07-25 19:57:58
 * @description 简单工厂模式的工厂
 */
public class Factory {
    //静态工厂方法
    public static Fruit getFruit(String name) {
        Fruit fruit = null;
        if (name.equals("苹果")) {
            fruit = new AppleFruit(name);
        } else if (name.equals("西瓜")) {
            fruit=new MelonFruit(name);
        }else {
            System.out.println("没有这种水果");
        }
        return fruit;
    }

}

实现类

/**
 * @author 21050
 * @date 2022-07-25 20:05:57
 * @description
 */
public class AppleFruit extends Fruit{
    @Override
    public void growingFruit() {
        System.out.println("我是水果"+fruitName+"长在树上,需要工人来树上采摘我");
    }

    public AppleFruit(String fruitName) {
        super(fruitName);
    }
}
/**
 * @author 21050
 * @date 2022-07-25 20:07:57
 * @description
 */
public class MelonFruit extends Fruit{
    public MelonFruit(String fruitName) {
        super(fruitName);
    }

    @Override
    public void growingFruit() {
        System.out.println("我是水果"+fruitName+"长在地上,需要工人们来地上采摘我");
    }

}

客户

/**
 * @author 21050
 * @date 2022-07-25 20:12:26
 * @description
 */
public class Client {
    public static void main(String[] args) {
        Fruit fruit=null;
        fruit=Factory.getFruit("苹果");
        System.out.println("我想知道这个水果怎么生长的");
        fruit.growingFruit();
        fruit.transportation();
    }
}

image-20220725202012861

优化

此时我们还可以发现这个时候仍旧当我们需要更改水果的时候,此时仍旧需要在main方法中读取这个信息,如果此时客户给我们一个单子,上面列满的水果,那么我们就需要重新传输很多参数,同时也不符合开闭原则,如果能将这个写入到xml文件中,那就好了

<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <fruitType>苹果</fruitType>
</config>
package 设计模式.简单工厂模式.example1;

import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import java.io.*;


/**
 * @author 21050
 * @date 2022-07-25 20:30:01
 * @description 此方法用于从xml文件中读取配置
 */
public class XMLUtil {
    public static String getFruitType() {
        try {
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
            Document doc = (Document) dBuilder.parse(new File("D:\\算法\\src\\设计模式\\简单工厂模式\\example1\\FruitList.xml"));
            NodeList n1 = doc.getElementsByTagName("fruitType");
            //在这里如果一次性得到很多的节点,那么使用for循环进行操作,同时工厂中也可以使用for循环
            Node classNode = n1.item(0).getFirstChild();
            String fruitType = classNode.getNodeValue().trim();
            return fruitType;

        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

创建对象和使用对象

在开发中建议将创建对对象和使用对象分开,降低程序之间的耦合,如果创建对象与使用对象在一个类中共同使用

class LoginAction {
	private UserDAO udao;
	
	public LoginAction() {
		udao = new JDBCUserDAO(); //创建对象
	}
	
	public void execute() {
		//其他代码
		udao.findUserById(); //使用对象
		//其他代码
	}
}

假如说下面的类使用JDBCUserDAO()这个子类的方法,那么现在我需在这个类中使用另外一个子类的方法,那么现在就需要更改构造器,这样改变源码,不符合开闭原则。

同时我们也需要注意到,并不是每一次创建对象都需要我们开启工厂模式,比如String类,我们直接调用构造方法即可,而不是要根据特定的字符串创建不同的字符串类,如果真的这样的话,那么Java中可能要包含所有语言的所有组合的字符串了。

优缺点

简单工厂模式的主要优点如下:

   (1) 工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。

   (2) 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。

   (3) 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点:

(1) 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。

   (2) 使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度。

   (3) 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

   (4) 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

适用场景:

(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。

(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值