设计模式| 04 工厂方法模式

公众号配套刷题小程序,有题目,有文章,有源码可下载

免费刷题,你值得拥有

点击进入

持续更新中,

大家有什么建议可以在评论区留言

或者直接发送到公众号

欢迎来撩客服小姐姐鸭

开头说几句

博主的博客地址:https://www.jeffcc.top/
推荐入门学习设计模式java版本的数据Head First 《设计模式》

什么是工厂方法模式

专业定义:工厂方法模式定义了一个创建对象的接口,但是由子类决定实例化的类是哪一个。工厂方法让实例化延迟到了子类。
博主的理解:工厂方法其实也是使用了把不变的部分和变化的部分分开封装起来的设计原则,将变化的部分提供一个抽象方法来交给子类来实现,不变的部分由工厂完成封装。
这种设计可以将对象的创建封装起来,以便得到更加松耦合,更有弹性的设计。

设计原则

  1. 依赖倒置原则,要依赖抽象,不要依赖具体类,具体做法是需要高层组件(工厂)和底层组件(实现类)之间不要有太多的依赖关系,而是可以通过一个共同的抽象类(工厂产生的对象)来实现依赖倒置。

  2. 多用组合,少用继承。

  3. 针对接口编程,而不是针对实现编程。

  4. 为交互对象之间的松耦合设计而努力。

  5. 类应该对外开放拓展,对修改关闭。

设计要点

  1. 所有的工厂都是用来封装对象的创建的。

  2. 工厂方法使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象。

  3. 工厂方法允许类的实例化延迟到子类。

设计实现

设计背景

一家披萨店需要拓展加盟业务,届时会有许多不同地方口味的披萨出现,而我们需要做的就是设计一个工厂来让加盟商使用,具体的风味的披萨由加盟商自己决定,工厂只负责包装等内容。

代码实现
项目结构

项目类图

披萨工厂
package factory;
import pizza.Pizza;
/** * 披萨工厂 */public abstract class PizzaStore {
public Pizza orderPizza(String type){        Pizza pizza;//        进行创建pizza        pizza = createPizza(type);//        下面进行的是共同的东西,所以封装起来到工厂中        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();
return pizza;
    }
/**     * 抽取出一个抽象的制作pizza的方法来交给子类具体实现     * 工厂模式的关键所在     * @param type  什么风味的pizza     * @return     */public abstract Pizza createPizza(String type);
}
ChicagoPizzaStore加盟店
package store;
import factory.PizzaStore;import pizza.Pizza;import pizza.impl.ChicagoStyleCheesePizza;
/** * ChicagoPizzaStore加盟店 */public class ChicagoPizzaStore extends PizzaStore {
/**     * 模拟测试生产pizza  太多类型了就写一个 理论可以无限拓展     * @param type 什么风味的pizza     * @return     */@Overridepublic Pizza createPizza(String type) {if ("cheese".equals(type)) {return new ChicagoStyleCheesePizza();        } else {return null;        }    }}
NYpizza加盟店
package store;
import factory.PizzaStore;import pizza.Pizza;import pizza.impl.NYStyleCheesePizza;
/** * 纽约pizza加盟店 */public class NYPizzaStore extends PizzaStore {
/**     * 模拟测试生产pizza  太多类型了就写一个 理论可以无限拓展     * @param type 什么风味的pizza     * @return     */@Overridepublic Pizza createPizza(String type) {if ("cheese".equals(type)) {return new NYStyleCheesePizza();        } else {return null;        }    }}
披萨抽象类(关键)
package pizza;
import java.util.ArrayList;
/** * pizza的抽象类 * 也就是之前说的依赖倒置所依赖的类!!! * 需要有pizza的操作的方法 */public abstract class Pizza {
public String name;//pizza名称public String dough;//pizza面团类型public String suace;//pizza酱料类型public ArrayList<String> toppings = new ArrayList<>(); //佐料

/**     * 提供默认的基本做法 进行烘烤、切片、装盒 如果需要可以进行重写     */public void prepare() {        System.out.println("Preparing" + name);        System.out.println("Tossing dough...");        System.out.println("Adding toppings:");        toppings.forEach(topping -> {            System.out.println("  " + topping);        });
    }
/**     * 烘烤     */public void bake() {        System.out.println("Bake for 25 minutes at 350");    }
/**     * 切片     */public void cut() {        System.out.println("Cutting the pizza into diagonal slices!");    }
/**     * 装盒     */public void box() {        System.out.println("Place pizza in official PizzaStore box");    }
public String getName() {return name;    }}

ChicagoStyleCheesePizza
package pizza.impl;import pizza.Pizza;
/** * 实现不同的风味的pizza ChicagoStyleCheesePizza */public class ChicagoStyleCheesePizza extends Pizza {

/**     * 设置风味     */public ChicagoStyleCheesePizza() {        name = "Chicago Style Deep Dish Cheese Pizza";        dough = "Extra Thick Curst Dough";        suace = "Plum Tomato Suace";        toppings.add("Shredded Mozzarella Cheese");    }

/**     * 模拟需要有不同的切片方法     */    @Overridepublic void cut() {        System.out.println("Cutting the pizza into square slices");    }}
NYStyleCheesePizza
package pizza.impl;import pizza.Pizza;
/** * 实现不同的风味的pizza 纽约风味 */public class NYStyleCheesePizza extends Pizza {
/**     * 设置风味     */public NYStyleCheesePizza() {        name = "NY Style Sauce and Cheese Pizza";        dough="Thin Curst Dough";        suace="Marinara Suace";        toppings.add("Grated Reggiano Cheese");    }}
测试买pizza
package test;import factory.PizzaStore;import pizza.Pizza;import store.ChicagoPizzaStore;import store.NYPizzaStore;
public class BuyPizza {public static void main(String[] args) {
//        找到NY店PizzaStore nyPizzaStore = new NYPizzaStore();Pizza pizza1 = nyPizzaStore.orderPizza("cheese");System.out.println("jay order a "+pizza1.getName()+"\n");
//        Chicago店PizzaStore chicagoPizzaStore = new ChicagoPizzaStore();Pizza pizza2 = chicagoPizzaStore.orderPizza("cheese");System.out.println("jeff order a "+pizza2.getName()+"\n");    }}
输出结果

最后说两句

工厂方法让子类决定要实例化的类是哪一个,这句话的理解并不是指模式允许子类本身在运行时做出决定,而是要在编写创建者类的时候,不需要知道实际所创建的产品是哪一个,选择了使用哪一个子类,也就“决定”了实际创建的产品是什么。
接下来会出一篇关于抽象工厂模式的文章 和工厂方法模式有一定的相通性。

你来问,我来答

交流群里很活跃

有小白,有大佬

你来还是不来?来!

扫描下方二维码,加小刀微信,

拉你进群哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值