小白也能看懂的工厂模式

在学习设计模式的时候,一开始对其中的工厂方法模式和抽象工厂模式有点混淆,网上查了一下,发现知乎也有人对这个问题进行提问,看来不止我不懂。一番学习好,发现其实很好理解。于是就有这篇文章的输出

要了解抽象工厂模式,就要先了解一下简单工厂模式和工厂方法模式,这几种工厂模式,是一步步迭代升级。至于实际工作用哪个更好呢,就要结合具体需求了。接下来的实例,不打算画UML图了,毕竟是面向小白,UML可能看不懂,也不对概念进行介绍了,需要的自行网上一搜就一大堆了。就以实际需求变动为例子,一步步介绍怎样通过不同的设计模式去应用。

作为Android程序员,最熟悉就是手机了,接下来就通过工厂生产手机作为例子。

普通写法

只有一个产品,正常写法就是如下,直接创建

# Client.java
/**使用手机的用户*/
public class Client {
    public static void main(String[] args) {
        MiPhone miPhone = new MiPhone();
        miPhone.play();
    }
}


# MiPhone.java
/**小米手机对象类*/
public class MiPhone {
    public void play(){
        System.out.println("使用小米手机");
    }
}

如果某一天有钱想换成iphone,那应该怎样改了?

# Client.java
public class Client {
    public static void main(String[] args) {
        //MiPhone miPhone = new MiPhone();
        //miPhone.play();
        Iphone iphone = new Iphone();
        iphone.play();
    }
}


# IPhone.java
/**新增的iphone手机对象类*/
public class Iphone {
    public void play(){
        System.out.println("使用苹果手机");
    }
}

Client中,我们就才写了两行,都要全部换掉了,如果还有更多的方法,不都要全部一个个改吗?而且,这里的产品的创建是在Client中,正常逻辑我们又不会自己生产手机。这个时候,就可以采用简单工厂模式,专业的东西就让专业的工厂去做。

简单工厂模式

# SimpleFactory.java
/**新建一个工厂内,通过传递不同的参数,创建不同的产品并返回*/
public class SimpleFactory {

    public static final String XIAOMI = "xiaomi";

    @Nullable
    public static ImplPhone createPhone(String phoneName){
        if (XIAOMI.equals(phoneName)){
            return new MiPhone();
        }
        return null;
    }
}

# ImplPhone.java
/**定义一个手机的接口*/
public interface ImplPhone {
    void play();
}

/**每个具体产品都去实现该接口并实现方法*/
public class MiPhone implements ImplPhone {
    @Override
    public void play() {
        System.out.println("使用小米手机");
    }
}

public class Client {
    public static void main(String[] args) {
        // 往工厂类中传递不同的值,就可以得到对应的产品。
        ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);
        implPhone.play();
    }
}

简单工厂模式,就是创建一个工厂类SimpleFactory,往工厂类根据传递不同的参数进行条件判断,生成返回不同的产品类。

这样改动,就可以避免两个问题:

  1. 把产品对象的创建,统一放在工厂类处理,而不是客户端自己创建

  2. 如果想换手机,直接传递不同的参数就好了。

使用简单工厂模式,应对更换手机的代码修改

public class SimpleFactory {
   
    public static final String XIAOMI = "xiaomi";
    public static final String APPLE = "apple";
   
    public static ImplPhone createPhone(String phoneName){
        if (XIAOMI.equals(phoneName)){
            return new MiPhone();
        }else if (APPLE.equals(phoneName)) {
            return new IPhone();
        }
        return null;
    }
}
   
# Iphone.java
public class IPhone implements ImplPhone {
    @Override
    public void play() {
        System.out.println("使用苹果手机");
        }
}
   
public class Client {
    public static void main(String[] args) {
        // 换成苹果手机,就直接传递不同参数生产Iphone手机了
        //ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);、
        ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.APPLE);、
            implPhone.play();、
    }
}

工厂方法模式

简单工厂模式,基本就可以满足我们的要求,但是接下来每次新增一个产品,都要去修改SimpleFactory类,这个就不满足我们的设计模式原则,尽量不要影响之前的类。于是,工厂方法模式闪亮登场。

# ImplFactory.java
/**定义一个工厂类*/
public interface ImplFactory {
    ImplPhone cratePhone();
}

# MiFactory.java
/**实现工厂类,定义一个小米工厂,用于生产小米手机*/
public class MiFactory implements ImplFactory {
    @Override
    public ImplPhone cratePhone() {
        return new MiPhone();
    }
}

# AppleFactory.java
/**实现工厂类,定义一个苹果工厂,用于生产iphone手机*/
public class AppleFactory implements ImplFactory {
    @Override
    public ImplPhone cratePhone() {
        return new IPhone();
    }
}

public interface ImplPhone {
    void play();
}

public class MiPhone implements ImplPhone {
    @Override
    public void play() {
        System.out.println("使用小米手机");
    }
}

public class IPhone implements ImplPhone {
    @Override
    public void play() {
        System.out.println("使用苹果手机");
    }
}

public class Client {

    public static void main(String[] args) {
        ImplFactory factory = new MiFactory();
        // 如果想换手机,只需修改创建的工厂类
        // ImplFactory factory = new AppleFactory();
        ImplPhone phone = factory.cratePhone();
        phone.play();
    }
}

用了工厂方法模式,如果新增产品,比如想换华为呢,只需要新建一个华为工厂类去实现工厂接口,和新建一个华为手机内去实现手机接口,就不需要对原来的代码进行修改了。但是,人人一部手机是不够,还要平板了。。。于是,ipad,miPad就都出来了!

抽象工厂模式

上面的ImplFactory只是cratePhone(),根本就没办法生产平板,那么,就加多条生产线生产,能赚钱的机会怎么可以错过呢?

# ImplFactory.java
/**在原来的抽象工厂中,进行修改,增加一条平板的生产线,也就是添加一个方法*/
public interface ImplFactory {
    ImplPhone cratePhone();
    ImplPad createPad();
}

public class AppleFactory implements ImplFactory {
    @Override
    public ImplPhone cratePhone() {
        return new IPhone();
    }

    @Override
    public ImplPad createPad() {
        return new Ipad();
    }
}

public class MiFactory implements ImplFactory {
    @Override
    public ImplPhone cratePhone() {
        return new MiPhone();
    }

    @Override
    public ImplPad createPad() {
        return new MiPad();
    }
}

public interface ImplPad {
    void play();
}

public class Ipad implements ImplPad {
    public void play(){
        System.out.print("使用ipad");
    }
}

public class MiPad implements ImplPad {
    public void play(){
        System.out.print("使用小米pad");
    }
}


public class Client {

    public static void main(String[] args) {
        ImplFactory factory = new MiFactory();
        ImplPhone phone = factory.cratePhone();
        phone.play();

        ImplPad pad = factory.createPad();
        pad.play();
    }
}

改动还是挺大的,但至少能实现需求。接下来有其他厂商也要生产手机和平板,只需要实现ImplFactory就可以了。其实,上面的处理方式,就是抽象工厂模式

啊?别惊讶,一不小心就应用上了。仔细对比一下区别就可以理解:

工厂方法模式,重点在方法,通过实现同一个方法,就可以创建不同的产品。
抽象工厂模式,是在工厂方法模式发展上去的,方法也可以创建不同的产品,但是,这个工厂接口,变更加抽象了,在里面可以实现多个方法,而不是单一产品了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,741评论 0 14
  • 字节跳动飞书内推!北京、杭州、武汉、广州、深圳、上海,六大城市等你来投。感兴趣的朋友可以私我咨询&内推,也可以通过...
    卢卡斯哔哔哔阅读 610评论 0 3
  • 前言 关于设计模式,是一个永远说不完的也说不清的话题。毕竟在编程的世界里,没有最好的设计模式,只有最合适的设计模式...
    VV木公子阅读 1,477评论 0 9
  • 分割线下面都是被揭开的谜团。 这里是这个故事真正的大纲。 冉染,女孩,小时候被父亲冉宏阳给了一副九连环。冉之阳说,...
    时间轮回中的七月之雨阅读 309评论 0 0
  • 万能的大熊 著 心比天高,命比纸薄 我自己是一个积极向上的人,也自然希望能够影响别人积极向上一点。但是当你发现有些...
    孙晓丽阅读 139评论 0 0