程序猿学社的GitHub,欢迎Star
github技术专题
本文已记录到github
通过上一篇文章,我们已经知道程序猿是有女(男)朋友,也知道如何保证只会有一个对象(男女朋友),本文我们来看一看工厂模式。
社长:“老王,我们开始继续23中设计模式之工厂模式”
隔壁老王: “社长,工厂模式有什么用,为什么要用工厂模式?”
社长: “我先买一个小关子,先来看一看传统的写法”
周末一大早,6点钟左右,我就被吵醒,然后一脸呆萌呆萌的看着我,原来是忘记给我家乖乖喂食物咯,看了一下存放猫粮的袋子,也弹尽粮绝咯,只能上宠物店去购买猫粮。他的名字叫汤圆
通过代码,我们实现去宠物店购买猫粮的这样一个需求。
package com.cxyxs.designmode.factory;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/3 23:16
* Modified By:
*/
public interface PetShop {
void buy();
}
class Meat implements PetShop{
@Override
public void buy() {
System.out.println("社长给汤圆购买肉干");
}
}
/**
* 提供者
* =======================
* 调用者
*/
class Test{
public static void main(String[] args) {
PetShop ps = new Meat();
ps.buy();
}
}
隔壁老王: “社长,你也说了,上面这种方式,提供者一变,调用者就得跟着变,在项目开发过程中,如何也出现这样的问题,那大家还能不能愉快的玩耍咯”
社长:“别急,我们可以通过简单工厂来实现”
从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例
肉干毕竟不能当饭吃,所以,还得买猫粮,肉干只能当零食吃。所以这时候我们的需求又发生了改变。
package com.cxyxs.designmode.factory.simple;
/**
* Description:宠物店
* Author: 程序猿学社
* Date: 2020/4/3 23:16
* Modified By:
*/
public interface PetShop {
void buy();
}
class Meat implements PetShop{
@Override
public void buy() {
System.out.println("社长给汤圆购买肉干");
}
}
class Foot implements PetShop{
@Override
public void buy() {
System.out.println("社长给汤圆购买猫粮");
}
}
class CatFootFacoty{
public static PetShop buy(String name){
switch (name){
case "猫粮":
return new Foot();
case "肉干":
return new Meat();
}
return null;
}
}
/**
* 提供者代码
* =======================
* 调用端代码
*/
class Test{
public static void main(String[] args) {
PetShop ps = CatFootFacoty.buy("肉干");
PetShop ps1 = CatFootFacoty.buy("猫粮");
ps.buy();
ps1.buy();
}
}
缺点:
跟简单工厂相比,工厂方法模式是简单工厂的plus版本,越来越流程化。不像简单工厂一个工厂,既生产肉干,又生产猫粮等等,工厂方法模式,就是把具体生产的工作,交给具体的工厂来负责,例如,生产肉干的是一个工厂,生产猫粮的又是一个工厂。
社长: “我们刚刚已经了解到简单工厂一些优缺点,其中很重要的一点就是不符合开闭原则,我们来看一看工厂方法模式”
社长: “既然工厂方法模式是简单工厂的plus版本,我们直接把简单工厂的代码拿过来,新创建一个包methodmodel,老王,有没有跟上我的节奏”
隔壁老王: “欧了,已经搞定咯,如何改造成工厂方法模式*
社长: "话不多说,先看看类图,再看代码 "
package com.cxyxs.designmode.factory.methodmodel;
/**
* Description:宠物店
* Author:程序猿学社
* Date: 2020/4/3 23:16
* Modified By:
*/
public interface PetShop {
void buy();
}
class Meat implements PetShop {
@Override
public void buy() {
System.out.println("社长给汤圆购买肉干");
}
}
class Foot implements PetShop {
@Override
public void buy() {
System.out.println("社长给汤圆购买猫粮");
}
}
interface Factory{
PetShop food();
}
class MeatFactory implements Factory{
@Override
public PetShop food() {
return new Meat();
}
}
class FootFactory implements Factory{
@Override
public PetShop food() {
return new Foot();
}
}
/**
* 提供者代码
* =======================
* 调用端代码
*/
class Test{
public static void main(String[] args) {
Factory factory = new MeatFactory();
FootFactory footFactory = new FootFactory();
PetShop food = factory.food();
PetShop food1 = footFactory.food();
food.buy();
food1.buy();
}
}
隔壁老王: “社长,你这代码,我没有看出什么好处来,只知道你这代码越来越复杂,绕的头都晕咯。”
社长: “老王,别急呀,我们之前已经知道简单工厂是不符合开闭原则的,也就是说,尽量不要在已经的代码上进行修改,应该进行扩展”
社长: “我家的汤圆现在已经不满足于肉干和猫粮咯,需要吃鱼,我们看看,我们如何在现有的代码上进行改动”
/**
* 扩展吃鱼的部分开头
*/
class Fish implements PetShop {
@Override
public void buy() {
System.out.println("社长给汤圆购买小鱼鱼");
}
}
class FishFactory implements Factory{
@Override
public PetShop food() {
return new Fish() ;
}
}
/**
* 提供者代码
* =======================
* 调用端代码
*/
class Test{
public static void main(String[] args) {
Factory factory = new MeatFactory();
FootFactory footFactory = new FootFactory();
Factory fishFactory = new FishFactory();
PetShop food = factory.food();
PetShop food1 = footFactory.food();
PetShop food2 = fishFactory.food();
food.buy();
food1.buy();
food2.buy();
}
}
好处:
隔壁老王: “就拿你上面main方法里面的MeatFactory举例,假设MeatFactory类变为MeatFactory123,还是需要修改提供者和调用者两边的代码”
社长 “工厂名称有一套规范,只需要提供者保证尽量不改动类名就行,不然就是一个死循环,看看mybatis工厂类,版本变动,工厂名也不会变动。mybatis开发就相当于提供者,我们使用人员,就相当于调用者,如果mybatis工厂名变动,我们开发也不知道,这体验是不是很不好。所以,这个问题,不用担心,都有规范的”
社长: “我们之前只是很简单的实现吃,猫还会吃、睡等行为(多个产品等级)。产品等级一多,工厂类就会变得越来越臃肿”
package com.cxyxs.designmode.factory.abstrastinterface;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/4 18:20
* Modified By:
*/
public interface Foot {
void eat();
}
class Meat implements Foot{
@Override
public void eat() {
System.out.println("给汤圆吃肉干");
}
}
class Fish implements Foot{
@Override
public void eat() {
System.out.println("给汤圆吃小鱼仔");
}
}
interface Toy{
void play();
}
class CatTeaser implements Toy{
@Override
public void play() {
System.out.println("社长利用逗猫棒跟汤圆玩耍");
}
}
class Ball implements Toy{
@Override
public void play() {
System.out.println("汤圆一个人跟小球进行玩耍");
}
}
/**
* 食物工厂代码
*/
interface FootFactory{
public Foot proFoot();
}
class MeatFactory implements FootFactory{
@Override
public Foot proFoot() {
return new Meat();
}
}
class FishFactory implements FootFactory{
@Override
public Foot proFoot() {
return new Fish();
}
}
/**
* 玩具工厂
*/
interface ToyFactory{
public Toy proToy();
}
class CatTeaserFactory implements ToyFactory{
@Override
public Toy proToy() {
return new CatTeaser();
}
}
class BallFactory implements ToyFactory{
@Override
public Toy proToy() {
return new Ball();
}
}
package com.cxyxs.designmode.factory.abstrastinterface.plus;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/4 18:20
* Modified By:
*/
public interface Foot {
void eat();
}
class Meat implements Foot {
@Override
public void eat() {
System.out.println("给汤圆吃肉干");
}
}
class Fish implements Foot {
@Override
public void eat() {
System.out.println("给汤圆吃小鱼仔");
}
}
interface Toy{
void play();
}
class CatTeaser implements Toy {
@Override
public void play() {
System.out.println("社长利用逗猫棒跟汤圆玩耍");
}
}
class Ball implements Toy {
@Override
public void play() {
System.out.println("汤圆一个人跟小球进行玩耍");
}
}
/**
* 食物工厂代码
*/
interface Factory{
public Foot proFoot();
public Toy proToy();
}
class MeatAndCatTeaserFactory implements Factory {
@Override
public Foot proFoot() {
return new Meat();
}
@Override
public Toy proToy() {
return new CatTeaser();
}
}
class FishAndBallFactory implements Factory{
@Override
public Foot proFoot() {
return new Fish();
}
@Override
public Toy proToy() {
return new Ball();
}
}
优点:
缺点:
隔壁老王: “社长,在抽象工厂模式中,吃和玩都是捆绑的关系,你这是捆绑销售,如果,我只想要实现吃,应该怎么办?”
社长: “如果只想实现吃,就可以使用工厂方法模式,应该根据具体问题,具体选择,使用那个模式。”
总结:
原创不易,不要白嫖,觉得有用的社友,给我点赞,让更多的老铁看到这篇文章。
因技术能力有限,如文中有不合理的地方,希望各位大佬指出,在下方评论留言,谢谢,希望大家一起进步,一起成长。
作者:程序猿学社
原创公众号:『程序猿学社』,专注于java技术栈,分享java各个技术系列专题,以及各个技术点的面试题。
原创不易,转载请注明来源(注明:来源于公众号:程序猿学社, 作者:程序猿学社)。