设计模式--工厂模式

一、简单工厂
举个栗子:
开个披萨店:

Pizza orderPizza() {
    Pizza pizza = new Pizza(); //创建个pizza
    pizza.prepare(); //备料
    pizza.bake(); //烘烤
    pizza.cut(); //切片
    pizza.box(); //装盒
}

披萨店不能只有一种披萨,要做各种类型的披萨怎么办呢?

Pizza orderPizza(String type) {//要做什么pizza就传入pizza的种类
    Pizza pizza;
if (type.equals(“cheese”)) { //根据pizza的类型,来实例化正确的具体类
        pizza = new CheesePizza();
} else if ...
    
    pizza.prepare(); //备料
    pizza.bake(); //烘烤
    pizza.cut(); //切片
    pizza.box(); //装盒
}

披萨店扩张了,制作的披萨种类更多了,有些披萨卖得不好,不做了,这怎么做呢?
只能在上面代码里删掉一些if else,再添加上一些if else。在上面这段代码中,if else这段会随着需求的变化而变化,但对披萨的备料,烘烤等操作是不会变化的。

Tips:
开闭原则:
扩展开放,对修改关闭。一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。

很明显,上面的这种设计,违背了开闭原则,这就到了使用封装的时候了。把会经常修改的if else这段代码抽离到另一个对象中,这个对象只负责创建披萨。
这个新对象SimplePizzaFactory就称为“工厂”,专门用来生产不同种类的披萨,orderPizza()就是这个对象的客户,当需要披萨时,就叫披萨工厂做一个,至于怎么做,就不用关心了。
卖披萨分三步:
1.建个披萨工厂专门做披萨

public class SimplePizzaFactory { //只负责创建披萨
    public Pizza createPizza(String type) { //这个方法为所有用户实例化新对象
        Pizza pizza = null;

        if (type.equals(“cheese”)) { //之前的if else
            pizza = new CheesePizza();
        } else if ...

        return pizza;
     }
}

2.建个披萨店

public class PizzaStore {
    SimplePizzaFactory factory; //为披萨店PizzaStore加上对SimplePizzaFactory的引用
    public PizzaStore (SimplePizzaFactory factory) { //披萨店PizzaStore的构造器,以一个工厂做参数
        This.factory = factory;
    }
    public Pizza orderPizza (String type) {
        Pizza pizza;
        pizza = factory.createPizza(type);//通过传入类型来使用工厂加工披萨
        pizza.prepare(); //备料
        pizza.bake(); //烘烤
        ...
        return pizza;
    }
}

3.披萨卖起来了

pubic class PizzaTest {
    public static void main (String[] args) {
        SimplePizzaFactory factory = new SimplePizzaFactory();//创建一个披萨工厂
        PizzaStore story = new PizzaStore(factory); //建立一个披萨店,从披萨工厂里获取披萨
        store.orderPizza(“Cheese”);//选择披萨的具体口味
    }
}

简单工厂其实不是一个设计模式,反而比较像一种编程习惯,把变化的部分单独封装起来。

二、工厂模式
披萨店有了加盟店啦~~但是每个加盟店想提供适合自己所在区域口味的披萨,所以加盟店需要有一个适合自己的工厂。
还是卖披萨的那三步:
1.建一个专门生产纽约风味的披萨工厂

abstract class PizzaFactory { 
    public abstract Pizza createPizza();
}
public class NYPizzaFactory extent PizzaFactory {//继承抽象工厂类,创建具体的实例方法
    public Pizza createPizza(String type) { 
        ... //个性化定制纽约口味披萨
        return pizza;
    }
}

2.开个加盟店
到这里发现,加盟店也需要个性化定制啊,不能通用就是PizzaStore,也得有什么NYPizzaStore啊,那就把披萨店也抽象出来。

public abstract class PizzaStore { //创建一个抽象的披萨店PizzaStore类
    public Pizza orderPizza(String type) {//处理披萨订单
        Pizza pizza;
        pizza = createPizza(type);//调用的就是下方的createPizza方法,这个方法由各个加盟店自己定义,也就是说每个PizzaStore的子类都会覆盖createPizza()方法

        //pizza的后续制作不变,加盟店无法影响他们,加盟店只负责确定口味,在外部调用orderPizza,而orderPizza里的createPizza是加盟店自己定义的具体制作什么口味的披萨
        pizza.prepare(); //备料
        pizza.bake(); //烘烤
        ...
        return pizza;
    }
    protected abstract Pizza createPizza(String type);//由各个加盟店自己决定如何做披萨
}

现在就开个加盟店

public class NYPizzaStore extends PizzaStore {
    Pizza createPizza(String item) { //必须实现createPizza()方法,因为在PizzaStore里他是抽象的
        if (item.equals(“cheese”)) { //具体的披萨口味
            return new NYStyleCheesePizza();
        } else if ...
    }
}

3.卖个纽约风味的芝士披萨

public class PizzaTest {
    public Static void main(String[] args) {
        PizzaStroe nyStore = new NYPizzaStore();//建个纽约加盟店
        Pizza pizza = nyStore.orderPizza(“cheese”);//定个cheese披萨
    }
}

Tips:
重点解释abstract Pizza createPizza(String type);


设计模式--工厂模式_第1张图片
image.png

工厂模式用来封装对象的常见,通过让子类决定应该创建的对象,达到将对象创建的过程封装起来的目的。
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
工厂模式类图:


设计模式--工厂模式_第2张图片
image.png

三、抽象工厂模式
抽象工厂模式提供一个接口,用于创建相关或依赖对象的“家族”(敲黑板,重点),而不需要明确指定具体类。
抽象工厂的任务是定义一个负责创建一组产品的接口,这个接口内的每个方法都负责创建一个具体产品,同时利用实现抽象工厂的子类来提供这些具体的做法。

工厂方法用的是继承,而抽象工厂是通过对象的组合来实现。
再通过披萨店的例子,来看看抽象工厂模式。
还是卖披萨的那三步:
1.建立工厂
A.建一个专门生产纽约风味的披萨工厂

abstract class PizzaFactory { 
    public abstract Pizza createPizza();
}
public class NYPizzaFactory extent PizzaFactory {//继承抽象工厂类,创建具体的实例方法
    public Pizza createPizza(String type) { 
        ... //个性化定制纽约口味披萨
        return pizza;
    }
}

B.制作披萨所用的原料需要保证质量,就需要建立一家生产原料的工厂,这样每家加盟店都从这个原料工厂里进货,确保质量。但是各个加盟店所产披萨的口味不同,所需原料也有细微差别(纽约的芝士和芝加哥的芝士,口味上是不一样的),与建立披萨工厂的思想一样,还是先建立一个原料生产工厂,然后每个区域继承这个工厂,来生产自己各自口味的原料。
定义原料工厂接口,它负责创建所有的原料:

public interface PizzaIngredientFactory{
    public Dough createDough(); //生产面团
    public Sauce createSauce(); //生产酱料
    ...
}

那么纽约原料工厂生产的原料就是纽约口味的啦

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
    public Dough createDough() {
        return new ThinCrustDough();
    }
    public Sauce createSauce() {
        return new MarinaraSauce();
    }
    ...
}

需要使用原料工厂生产出的原料来制作披萨

public abstract class Pizza {
    Dough dough;
    Sauce sauce;
    ...//制作披萨所需的各种原料

    abstract void prepare();//把prepare()方法声明成抽象,由不同地区的原料工厂提供原料

    //之前的烘烤、切片等工序不变
    void back() {
    }
    void cut() {
    }
    ...
}

之后我们就可以使用原料工厂生产的原料来制作披萨啦,原料的质量得到了保证。
制作一个芝士披萨

public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;
    public CheesePizza (pizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }

    void prepare() {//从原料工厂里获取原料制作披萨
        dough = ingredientFactory.createDough();
        Sauce = ingredientFactory.createSauce();
        ...
    }
}

Tips:


设计模式--工厂模式_第3张图片
image.png

2.开个加盟店

public class NYPizzaStore extends PizzaStore {
    Protected Pizza createPizza(String item) {
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
        if (item.equals(“cheese”)) {
            //把工厂传递给每一个披萨,以便比萨从工厂中取得原料
            //具体从哪个工厂(纽约工厂?芝加哥工厂?),由上面那行代码决定
            pizza = new CheesePizza(ingredientFactory);
        } else if ...
        return pizza;
    }
}

3.卖个纽约风味的芝士披萨

public class PizzaTest {
    public Static void main(String[] args) {
        PizzaStroe nyStore = new NYPizzaStore();//建个纽约加盟店
        Pizza pizza = nyStore.orderPizza(“cheese”);//定个cheese披萨
    }
}

看看抽象工厂的类图


设计模式--工厂模式_第4张图片
image.png

结合披萨店再来看


设计模式--工厂模式_第5张图片
image.png

结合上面的类图再回顾下抽象工厂的定义,抽象工厂的任务是定义一个负责创建“一组”产品的接口,通过对象的“组合”来实现。
在披萨店的例子中,创建了三个接口:披萨,披萨店,披萨原料工厂,通过组合这三个接口,实现了对各个加盟店的控制:保证披萨的制作工艺,和原料供应

你可能感兴趣的:(设计模式--工厂模式)