工厂模式
简单工厂模式
1、什么是简单工厂模式?
答:简单工厂模式又叫静态工厂方法模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。比如,一台咖啡机就可以理解为一个工厂模式,你只需要按下想喝的咖啡品类的按钮(摩卡或拿铁),它就会给你生产一杯相应的咖啡,你不需要管它内部的具体实现,只要告诉它你的需求即可。
优点:(1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象;
(2)客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量;
(3)通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
缺点:(1)不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑;
(2)产品类型较多时,工厂的创建逻辑可能过于复杂,一旦出错可能造成所有产品的创建失败,不利于系统的维护。
简单工厂代码实现:
- 首先创建一个生产什么样口味的咖啡接口
public interface CoffeeProduct {
public String coffee();
}
- 实现咖啡接口决定要喝什么样的咖啡
public class MoKa implements CoffeeProduct {
@Override
public String coffee(){
return "摩卡";
}
}
public class NaTie implements CoffeeProduct {
@Override
public String coffee(){
return "拿铁";
}
}
- 创建生产咖啡的工厂类
public class FactoryCoffee {
public static CoffeeProduct getCoffeeProduct(String coffeeType) {
switch (coffeeType) {
case "natie":
return new NaTie();
case "moka":
return new MoKa();
default:
throw new RuntimeException("对不起,没有这种咖啡...");
}
}
public static void main(String[] args) {
//我要拿铁
String natie = FactoryCoffee.getCoffeeProduct("natie").coffee();
System.out.println("我要===" + natie);
//我要摩卡
String moka = FactoryCoffee.getCoffeeProduct("moka").coffee();
System.out.println("我要===" + moka);
//我要星冰乐
String xingbingle = FactoryCoffee.getCoffeeProduct("星冰乐").coffee();
System.out.println("我要===" + xingbingle);
}
}
这种简单工厂模式决定了你需要什么样的咖啡只管要就可以了,如果后期需要“星冰乐”,再去实现CoffeeProduct 需要生产什么样口味的咖啡接口就行了。但是缺点也来了,如果不想和咖啡,想喝奶茶怎么办,CoffeeProduct只能生产咖啡,它不卖奶茶,这时候需要用到抽象工厂模式。
抽象工厂模式
2、什么是抽象工厂模式?
抽象工厂模式是在简单工厂的基础上将未来可能需要修改的代码抽象出来,通过继承的方式让子类去做决定。
比如,以上面的咖啡工厂为例,某天我的口味突然变了,不想喝咖啡了想喝奶茶,这个时候如果直接修改简单工厂里面的代码,这种做法不但不够优雅,也不符合软件设计的“开闭原则”,因为每次新增品类都要修改原来的代码。这个时候就可以使用抽象工厂类了,抽象工厂里只声明方法,具体的实现交给子类(子工厂)去实现,这个时候再有新增品类的需求,只需要新创建代码即可。
抽象工厂代码实现:
抽象工厂模式的主要角色如下。
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
上面简单咖啡工厂代码保留
- 继续创建简单的奶茶工厂 和创建咖啡工厂一样直接贴代码
public interface NaiChaProduct {
public String naiCha();
}
public class CoCo implements NaiChaProduct{
@Override
public String naiCha(){
return "coco奶茶";
}
}
public class Yidiandian implements NaiChaProduct {
@Override
public String naiCha(){
return "一点点奶茶";
}
}
public class FactoryNaiCha {
public static NaiChaProduct getNaiChaProduct(String naiChaType) {
switch (naiChaType) {
case "coco":
return new CoCo();
case "yidiandian":
return new Yidiandian();
default:
throw new RuntimeException("对不起,没有这种奶茶...");
}
}
}
- 创建决定工厂是什么类型的工厂接口
public interface ProductType {
//什么工厂
public Object type();
}
- 各种工厂分别去实现这个接口
public class CoffeeType implements ProductType{
@Override
public Object type(){
return new FactoryCoffee();
}
}
public class NaichaType implements ProductType{
@Override
public Object type(){
return new FactoryNaiCha();
}
}
- 创建各种工厂的抽象工厂类
//创建抽象工厂类
public class AbstractFactory {
public static ProductType getType(String productType){
switch (productType){
case "咖啡":
return new CoffeeType();
case "奶茶":
return new NaichaType();
default:
throw new RuntimeException("不存在这种类型的工厂");
}
}
public static void main(String[] args) {
//我要拿铁
Object coffee = AbstractFactory.getType("咖啡").type();
Object naicha = AbstractFactory.getType("奶茶").type();
System.out.println(coffee.getClass().getName());
System.out.println(FactoryCoffee.class.getName());
if(coffee.getClass().getName().equals(FactoryCoffee.class.getName()) && naicha.getClass().getName().equals(FactoryNaiCha.class.getName())){
String natie = FactoryCoffee.getCoffeeProduct("natie").coffee();
String coco = FactoryNaiCha.getNaiChaProduct("coco").naiCha();
System.out.println("我要===" + natie + "+" +"我还要帮朋友带奶茶===" + coco);
}
}
}
如果以后要卖其他饮料或者其它商品,只需要继续造工厂即可,不需要修改之前的代码。抽象工厂就是工厂的工厂。
文章知识点概括来自