工厂设计模式

工厂设计模式

针对接口编程

针对接口编程,可以隔离掉以后系统可能发生的一大堆改变。为什么呢?如果代码是针对接口而写,那么通过多态,它可以与任何新类实现该接口。但是,当代码使用大量的具体类时,等于是自找麻烦,因为一旦加入新的具体类,就必须改变代码。也就是说,你的类并发“对修改”关闭。想用新的具体类型来扩展代码,必须重新打开它。

所以,该怎么办?当遇到这些问题时,就应该回到OO设计原则去寻找探索。我们的第一个原则用来处理改变,并帮助我们“找出会变化的方面,把他们从不变的部分分离出来”

工厂演变

原代码:

package com.learn.store;

import com.learn.entity.CheesePizza;
import com.learn.entity.GreekPizza;
import com.learn.entity.PepperoniPizza;
import com.learn.entity.Pizza;
import com.learn.factory.SimplePizzaFactory;

/**
 * @author weijie
 * @date 2020/7/8 11:05
 */
public class PizzaStore {

    /**
     * 预定比萨:
     * 【压力来自于增加更过的比萨类型】
     * 根据比萨类型,生成实例,但是这种缺点是以后需要动态添加、删除比萨时候,都需要改动这块代码
     * @return
     */
    Pizza orderPizza(String type){
        Pizza pizza = null;

        /**
         * 为了应对压力吗,我们需要封装这块代码,抽出的对象变成工厂
         */
        if (type.equals("cheese")){
            pizza = new CheesePizza();
        }else if (type.equals("greek")){
            pizza = new GreekPizza();
        }else if (type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }


}
package com.learn.entity;

/**
 * @author weijie
 * @date 2020/7/8 11:22
 */
public class Pizza {

    public void prepare(){
        System.out.println("准备 ...");
    }

    public void bake(){
        System.out.println("烘焙 ...");
    }

    public void cut(){
        System.out.println("切块 ...");
    }

    public void box(){
        System.out.println("装盒子 ...");
    }

}

package com.learn.entity;

/**
 * @author weijie
 * @date 2020/7/8 11:27
 */
public class CheesePizza extends Pizza {

    @Override
    public void prepare() {
    	System.out.println("CheesePizza");
        super.prepare();
    }

    @Override
    public void bake() {
        super.bake();
    }

    @Override
    public void cut() {
        super.cut();
    }

    @Override
    public void box() {
        super.box();
    }
}

package com.learn.entity;

/**
 * @author weijie
 * @date 2020/7/8 11:28
 */
public class GreekPizza extends Pizza {

    @Override
    public void prepare() {
        System.out.println("GreekPizza");
        super.prepare();
    }

    @Override
    public void bake() {
        super.bake();
    }

    @Override
    public void cut() {
        super.cut();
    }

    @Override
    public void box() {
        super.box();
    }
}

package com.learn.entity;

/**
 * @author weijie
 * @date 2020/7/8 11:29
 */
public class PepperoniPizza extends Pizza {

    @Override
    public void prepare() {
    	System.out.println("PepperoniPizza");
        super.prepare();
    }

    @Override
    public void bake() {
        super.bake();
    }

    @Override
    public void cut() {
        super.cut();
    }

    @Override
    public void box() {
        super.box();
    }
}

封装成简单工厂

package com.learn.factory;

import com.learn.entity.CheesePizza;
import com.learn.entity.GreekPizza;
import com.learn.entity.PepperoniPizza;
import com.learn.entity.Pizza;

/**
 * 【建立一个简单比萨工厂】
 * 改类主做一件事情,就是负责帮客户创建比萨
 * @author weijie
 * @date 2020/7/8 11:36
 */
public class SimplePizzaFactory {

    public Pizza createPizza(String type){
        Pizza pizza = null;
        if (type.equals("cheese")){
            pizza = new CheesePizza();
        }else if (type.equals("greek")){
            pizza = new GreekPizza();
        }else if (type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }
        return pizza;
    }

}

package com.learn.store;

import com.learn.entity.Pizza;
import com.learn.factory.SimplePizzaFactory;

/**
 * @author weijie
 * @date 2020/7/8 11:05
 */
public class PizzaStore {

    SimplePizzaFactory factory;

    public PizzaStore(SimplePizzaFactory factory){
        this.factory = factory;
    }

    public Pizza orderPizza(String type){
        Pizza pizza = factory.createPizza(type);

        /**
         * 【如果想要对一些质量控制】
         * 如果采用其他自创流程:采用不同的烘焙做法、不要切片、使用其他厂商盒子,此时没法控制
         * 目前所有方法绑定的太死了,没有弹性
         */
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }

}

运行:

package com.learn;

import com.learn.factory.SimplePizzaFactory;
import com.learn.store.PizzaStore;

/**
 * @author weijie
 * @date 2020/7/8 13:07
 */
public class Runner {

    public static void main(String[] args) {
        PizzaStore pizzaStore = new PizzaStore(new SimplePizzaFactory());
        pizzaStore.orderPizza("greek");
    }
}

输出:

Files\Java\jdk1.8.0_171\jre\lib\rt.jar;F:\lagou\design_pattern\target\classes" com.learn.Runner
GreekPizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...

Process finished with exit code 0

如果此时有比萨加盟店进来

将原来简单工厂,写出三种不同工厂,NYPizzaFactory(纽约工厂)、ChicagoPizzaFactory(芝加哥工厂)、CaliforniaPizzaFactory(加利福尼亚工厂)

public class CaliforniaPizzaFactory extends SimplePizzaFactory {
    @Override
    public Pizza createPizza(String type) {
        System.out.println("CaliforniaPizzaFactory");
        return super.createPizza(type);
    }
}
public class ChicagoPizzaFactory extends SimplePizzaFactory {
    @Override
    public Pizza createPizza(String type) {
        System.out.println("ChicagoPizzaFactory");
        return super.createPizza(type);
    }
}
public class NYPizzaFactory extends SimplePizzaFactory {
    @Override
    public Pizza createPizza(String type) {
        System.out.println("NYPizzaFactory");
        return super.createPizza(type);
    }
}

运行:

public class Runner {

    public static void main(String[] args) {
        PizzaStore pizzaStore = new PizzaStore(new ChicagoPizzaFactory());
        pizzaStore.orderPizza("greek");

    }
}

输出:

Files\Java\jdk1.8.0_171\jre\lib\rt.jar;F:\lagou\design_pattern\target\classes" com.learn.Runner
ChicagoPizzaFactory
GreekPizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...

如果此时想要多一些质量控制

如果采用其他自创流程:采用不同的烘焙做法、不要切片、使用其他厂商盒子,此时没法控制
目前所有方法绑定在PizzaStore,没有弹性。

将PizzaStore加抽象方法

public abstract class PizzaStore {
    Pizza orderPizza(String type){
        Pizza pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }


    abstract Pizza createPizza(String type);

}

现在已经有一个PizzaStore超类:让每个域类型:NYPizzaStore(纽约披萨店)、ChicagoPizzaStore(芝加哥披萨店)、CaliforniaPizzaStore(加利福尼亚披萨)都继承PizzaStore

public class NYPizzaStore extends PizzaStore {

    NYPizzaFactory factory;

    public NYPizzaStore(NYPizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza createPizza(String type) {
        System.out.println("NYPizzaStore");
        return factory.createPizza(type);
    }
}
public class ChicagoPizzaStore extends PizzaStore {

    ChicagoPizzaFactory factory;

    public ChicagoPizzaStore(ChicagoPizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza createPizza(String type) {
        System.out.println("ChicagoPizzaStore");
        return factory.createPizza(type);
    }
}
public class CaliforniaPizzaStore extends PizzaStore {

    CaliforniaPizzaFactory factory;

    public CaliforniaPizzaStore(CaliforniaPizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza createPizza(String type) {
        System.out.println("CaliforniaPizzaStore");
        return factory.createPizza(type);
    }
}

运行:

public class Runner {

    public static void main(String[] args) {
        NYPizzaStore nyPizzaStore = new NYPizzaStore(new NYPizzaFactory());
        nyPizzaStore.orderPizza("cheese");
    }
}

输出:

NYPizzaStore
NYPizzaFactory
CheesePizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...

让我们开一家披萨店吧!

public class NYPizzaStore extends PizzaStore {

    NYPizzaFactory factory;

    public NYPizzaStore(NYPizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza createPizza(String type) {
        System.out.println("NYPizzaStore");
        return factory.createPizza(type);
    }
}
public class NYPizzaFactory extends SimplePizzaFactory {

    @Override
    public Pizza createPizza(String type){
        Pizza pizza = null;
        if (type.equals("cheese")){
            pizza = new NYStyleCheesePizza();
        }else if (type.equals("veggie")){
            pizza = new NYStyleVeggiePizza();
        }else if (type.equals("clam")){
            pizza = new NYStyleClamPizza();
        }else if (type.equals("pepperoni")){
            pizza = new NYStylePepperoniPizza();
        }else {
            return null;
        }
        return pizza;
    }
}

现在来实现披萨本身

public class ChicagoStyleCheesePizza extends Pizza {

    public ChicagoStyleCheesePizza() {
        name = "深盘奶酪披萨";
        dough = "特厚皮面团";
        sauce = "李形番茄";

        toppings.add("切碎的Mozzarella酱");
    }


    @Override
    public void cut() {
        System.out.println("切成方形");
    }
}
public class NYStyleCheesePizza extends Pizza {

    public NYStyleCheesePizza() {
        name = "酱汁和奶酪披萨";
        dough = "薄皮面团";
        sauce = "纯番茄酱";

        toppings.add("磨碎的Reggiano奶酪");
    }
}
public class Runner {

    public static void main(String[] args) {
        NYPizzaStore nyPizzaStore = new NYPizzaStore(new NYPizzaFactory());
        ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore(new ChicagoPizzaFactory());

        nyPizzaStore.orderPizza("cheese");
        chicagoPizzaStore.orderPizza("cheese");
    }

}

输出:

NYPizzaStore
准备 ...
 磨碎的Reggiano奶酪
烘焙 ...
切块 ...
装盒子 ...
ChicagoPizzaStore
准备 ...
 切碎的Mozzarella酱
烘焙 ...
切成方形
装盒子 ...

认识工厂方法模式的时刻到了

所有工厂模式都用来封装对象的创建,工厂方法模式通过让子类决定改创建的对象是什么,来达到将对象创建的过程封装的目的·让我们看看类图有哪些组成元素

工厂设计模式_第1张图片

工厂设计模式_第2张图片

平行的类层级

将一个orderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法也可以被视为是一种框架,让我们来看看两个平行的类层级,认清它们关系
工厂设计模式_第3张图片

你可能感兴趣的:(设计模式,每日学习)