设计模式之----工厂模式

1、工厂模式概要

工厂模式可分为3中工厂模式

  • 简单(静态)工厂模式 :非设计模式,作用为将创建的过程从对象的使用者中分离开来

  • 工厂模式 : 将类的实例化推迟到子类

  • 抽象工厂模式 :为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

工厂模式的作用就是为了解耦,使我们在扩充功能的时候尽可能少的修改代码

2、简单工程模式

**定义:**简单工程模式是一种非设计模式,作用为将创建的过程从对象的使用者中分离开来

我们下面来举个例子

假设你是一个自动售卖机程序的编写者,你需要根据客户的选择来动态创建实例

public class beverageStore {

    public void orderBeverage(String str){

        Beverage beverage = null;

        if (str.equals("Cola")){
            beverage = new Cola();
        }else if (str.equals("Fanta")){
            beverage = new Fanta();
        }else if (str.equals("Sprite")){
            beverage = new Sprite();
        }

        beverage.sell();

    }

}

上面这个例子不难理解,可以根据客户的选择来实例化产品,然后卖给客户

但是呢,看到这个例子我们思考一个问题,我想要扩展这个类方便吗?

扩展可能需要以下几个步骤

①编写新饮料的实体类

②添加if else代码

如果只更新几个我们可能还能接受,如果一次更新许多的话,代码会混在一起,又臭又长

所以在这里我们介绍简单工厂模式,把实例化的部分从这里面去除

首先创建一个工程类

public class SimpleBeverageFactory {
    
    public Beverage createBeverage(String str){
        
        Beverage beverage = null;

        if (str.equals("Cola")){
            beverage = new Cola();
        }else if (str.equals("Fanta")){
            beverage = new Fanta();
        }else if (str.equals("Sprite")){
            beverage = new Sprite();
        }
        
        return beverage;
    }

}

很明显的是,我们只是把刚刚生产饮料的代码给复制过来了

然后我们看看BeverageStore.java这个类

public class BeverageStore {
    
    private SimpleBeverageFactory simpleBeverageFactory;

    public BeverageStore(SimpleBeverageFactory simpleBeverageFactory) {
        this.simpleBeverageFactory = simpleBeverageFactory;
    }

    public void orderBeverage(String str){

        Beverage beverage = simpleBeverageFactory.createBeverage(str);

        beverage.sell();

    }

}

可以简单来说,我们帮自动售卖机找到了一个生产的工程,把生产和销售的事情分开了,自动售卖机只需要处理销售的问题就行了。

简单工程模式的主要目的就是把创建对象的过程和对象的使用者分开,虽然代码编写并没有变的简单或怎么样,但是确确实实降低一点耦合,虽然不多,但确实降低了。

还有一种静态工程模式,只需要在工程类的方法上加上static关键字即可

3、工厂模式

定义: 将类的实例化推迟到子类

我们把刚刚的例子升级,现在我们的自动售卖机做大了,需要在学校和酒店门口投放,针对不同的地方,我们饮料的配方应该不同,比如在酒店我们可以推出”酒精可乐“,在学校呢我们可以推出“健脑可乐”,这个我们就需要针对不同的地方来进行不同的配置了

我们回顾一下刚刚学完的简单工程模式,能不能解决这个问题?

答案是可以的,我们只需要创建一个学校的生产工厂,一个酒店的生产工厂即可

但是呢,我们相要更好的方式,我们先看代码感受一下

public abstract class BeverageStore {


    abstract Beverage createBeverage(String str);


    public void orderBeverage(String str){

        Beverage beverage = createBeverage();

        beverage.sell();

    }

}

和简单工厂模式不同,我们选择创建一个抽象基类,同样的把生产和销售分开,强制子类重写生产方法(主要原因是,针对不同地区的饮料配方不同)

我们看看子类的方法

public class SchoolBeverageStore extends BeverageStore {


    @Override
    Beverage createBeverage(String str) {

        Beverage beverage = null;

        if (str.equals("TalcoholCola")){
            beverage = new TalcoholCola();
        }else if (str.equals("Fanta")){
            beverage = new Fanta();
        }else if (str.equals("Sprite")){
            beverage = new Sprite();
        }
        return beverage;
    }
    
}

这样,我们就形成了一种定制化的实例化方式,进一步的解耦合,为什么要这样做?

和简单工厂模式相比,我们这里减少了工厂类的编写,而且任然把生产和销售分开了,在维护和新增产品的时候,我们只需要在新的定制类里面添加代码即可。

看到这里你可能会有疑问,if-else的编写和维护并不是很困难啊?而且销售就一个方法sell,即使再多的类也可以很轻易的完成维护

其实这里的if-else只是一种举例情况,你可以把工厂模式运用到任何地方,在很多时间场景中业务代码可比这种复杂的多。

在这里,我们只学习工厂模式解耦合的思想。

4、抽象工厂模式

定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

简单来说,工厂模式解决的是同级不同类的问题,可乐,雪碧和芬达他们都属于同级产品饮料

抽象工厂方法解决的一族问题,比如生产可乐的过程中,我们需要二氧化碳,需要糖,需要水,这些可能会来自不同的工厂,我们如何通过代码来解耦合,让他们可以统一处理。

还是上面的自动售卖机例子,我们再把需求升级,现在针对不同地区的售卖机二氧化碳的含量可能不同,在学校的二氧化碳含量可能要低一点,而且糖要用焦糖,在酒店的二氧化碳含量要高一点,糖要用植物糖(我也不知道为什么)

public interface BeverageIngredientFactory {

     Sugar createSuagr();

     Co2 createCo2();
     
}

先创建一个饮料原料生产的工程

public class SchoolBeverageIngredientFactory implements BeverageIngredientFactory {


    @Override
    public Sugar createSuagr() {
        return new Sucrose_Sugar();
    }

    @Override
    public Co2 createCo2() {
        return new Co2_low();
    }
    
}

然后我们回到饮料类

public abstract class Beverage {

    public Co2 co2;
    
    public Sugar sugar;

    abstract void sell();

    abstract void prepare();


}

然后到具体实现类

public class School_Cola extends Beverage {

    private SchoolBeverageIngredientFactory factory;

    public School_Cola(SchoolBeverageIngredientFactory factory) {
        this.factory = factory;
    }

    @Override
    void sell() {
        System.out.println("this School_Cola");
    }

    @Override
    void prepare() {
        co2 = factory.createCo2();
        sugar = factory.createSuagr();
    }
}

我们引用到工程类,把所有原料整合起来,然后就能得到具体实现类,需要改变原来的时候只需要工程类中替换即可,进一步解耦合

其实我个人觉得在这里其实可以把工厂类替换成工厂方法中的继承关系

public class School_Cola extends Beverage {

    
    @Override
    void sell() {
        System.out.println("this School_Cola");
    }

    @Override
    void prepare() {
        co2 = new Co2_low();
        sugar = new Sucrose_Sugar();
    }
}

完全可以用工厂模式来解决这个问题,但是我觉得这样可能会体现不出来抽象工厂的含义。所以这个改动存疑?希望有知道的可以和我说一下

上一篇:设计模式之装饰者模式(二)


下一篇:设计模式:装饰器模式