简单工厂模式

引入

假设我们现在有一个需求;

设计一个咖啡店点餐系统;

设计一个咖啡类(Coffee),并定义其两个子类(A咖啡和B咖啡)

再设计一个咖啡店类(Store),咖啡店具有点咖啡的功能。

如图所示;
在这里插入图片描述
那么代码如下

package simple_factory;

public class Store {
    public Coffee orderCoffee(String coffeeName){
        if(coffeeName.equals("coffeeA")){
            return new ACoffee();
        }else if(coffeeName.equals("coffeeB")){
            return new BCoffee();
        }else{
            throw new RuntimeException("不存在这种Coffee");
        }
    }
}
-------
package simple_factory;

public abstract class Coffee {
    public abstract String getCoffeeName();
}
-------
package simple_factory;

public class ACoffee extends Coffee{
    @Override
    public String getCoffeeName() {
        return "A咖啡";
    }
}
-------
package simple_factory;

public class BCoffee extends Coffee{
    @Override
    public String getCoffeeName() {
        return "B咖啡";
    }
}

这样的设计有明显的缺点

  • 如果我们其他地方又需要点咖啡(比如外卖系统),那么判断咖啡种类的代码是会重复的;
  • 如果要新添咖啡种类,那么我们需要修改代码,违背了开闭原则

优化一

我们引入一个咖啡工厂,作为中间件,帮助咖啡店与咖啡解耦,咖啡店只需要与工厂打交道即可;

即使后期推出外卖类,也只需要与工厂打交道

如下图

在这里插入图片描述

代码如下,咖啡部分的代码不变,如优化前;

package simple_factory;

public class EasyCoffeeFactory {
    public static Coffee createCoffee(String coffeeName){
        if(coffeeName.equals("coffeeA")){
            return new ACoffee();
        }else if(coffeeName.equals("coffeeB")){
            return new BCoffee();
        }else{
            throw new RuntimeException("不存在这种Coffee");
        }
    }
}
---
package simple_factory;

public class Store {
    public Coffee orderCoffee(String coffeeName){
        return EasyCoffeeFactory.createCoffee(coffeeName);
    }
}

这样做,我们解决了上述的问题1,但是遇到新品种咖啡,我们依然需要修改代码,依然违反开闭原则

优化二

我们引入一个配置文件,实现极其简易的IOC容器;

命名为coffeeConfig.properties,内容如下;

coffeeA = simple_factory.ACoffee
coffeeB = simple_factory.BCoffee

我们只修改工厂部分的代码,其他部分不变;

package simple_factory;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import java.util.Set;

public class EasyCoffeeFactory {

    private static HashMap<String,Coffee> coffeeMap = new HashMap();

    static {
        Properties properties = new Properties();
        InputStream is = EasyCoffeeFactory.class.getClassLoader().getResourceAsStream("coffeeConfig.properties");
        try {
            properties.load(is);
            Set<Object> keySet = properties.keySet();
            //这里的key是配置文件中的coffeeA和coffeeB
            for (Object key : keySet) {
                String clsName = (String) properties.get(key);
                Class cls = Class.forName(clsName);
                Coffee coffee = (Coffee) cls.getDeclaredConstructor().newInstance();
                coffeeMap.put((String) key,coffee);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Coffee createCoffee(String coffeeName){
        return coffeeMap.get(coffeeName);
    }
}

这样以后需要添加新的咖啡的时候,就不需要改动这里的代码了;

只需要在配置文件中写上新的key以及全类名即可,如下;

coffeeA = simple_factory.ACoffee
coffeeB = simple_factory.BCoffee
coffeeC = simple_factory.CCoffee

当然目前这个工厂里的咖啡对象都是相同的,当然你也可以改写成不同的,怎样都行…

比如可以改成这样

package simple_factory;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Properties;
import java.util.Set;

public class EasyCoffeeFactory {

    private static HashMap<String,Constructor> coffeeMap = new HashMap();

    static {
        Properties properties = new Properties();
        InputStream is = EasyCoffeeFactory.class.getClassLoader().getResourceAsStream("coffeeConfig.properties");
        try {
            properties.load(is);
            Set<Object> keySet = properties.keySet();
            //这里的key是配置文件中的coffeeA和coffeeB
            for (Object key : keySet) {
                String clsName = (String) properties.get(key);
                Class cls = Class.forName(clsName);
                Constructor constructor = cls.getDeclaredConstructor();
                coffeeMap.put((String) key,constructor);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Coffee createCoffee(String coffeeName) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        return (Coffee) coffeeMap.get(coffeeName).newInstance();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值