设计模式——工厂设计模式

什么是工厂设计模式?

将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定,工厂设计模式是将拥有共性的产品抽象封装到工厂类中统一进行管理和创建,以达到降低使用者与产品之间的耦合度的目的一种手段。在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

本篇主要介绍三种工厂设计模式的使用:

1、简单工厂
2、工厂方法
3、抽象工厂

参考文章:
https://www.jianshu.com/p/38493eb4ffbd
https://blog.csdn.net/bruceleenumberone/article/details/73888726

1、简单工厂

定义:一个工厂方法,依据传入的参数,生成对应的产品对象;

我们以汽车为例讲解工厂模式。

Car.java源码如下:

public interface Car {
    void run();
}

Audi.java源码如下:

public class Audi implements Car {
    @Override
    public void run() {
        System.out.println(getClass().getSimpleName() + " run...");
    }
}

BMW.java源码如下:

public class BMW implements Car {
    @Override
    public void run() {
        System.out.println(getClass().getSimpleName() + " run...");
    }
}

CarFactory.java源码,这个类专门负责创建对象:

public class CarFactory {

    public static Car create(String type) {
        if ("audi".equals(type)) {
            return new Audi();
        } else if ("bmw".equals(type)) {
            return new BMW();
        } else {
            return null;
        }
    }
}

Client.java源码如下:

public class Client {
    public static void main(String[] args) {
        Car car1 = CarFactory.create("audi");
        Car car2 = CarFactory.create("bmw");
        car1.run();
        car2.run();
    }
}

控制台输出:

Audi run...
BMW run...

要点:

  • 1 简单工厂模式也叫静态工厂模式,就是工厂类一般使用静态方法,通过接收的参数的不同的对象的不同来返回不同的对象实例。
  • 2 对于增加新产品无能为力!不修改代码的话,是无法扩展的。需要修改CarFactory这个类
  • 3 一般使用较多还是简单工厂模式。

2、工厂方法

工厂方法模式要点:
1)为了避免简单工厂模式的缺点,不完全满足OCP(开闭原则)。
2)工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。

修改汽车工厂CarFactory.java接口的源码:

public interface CarFactory {
    Car createCar();
}

新增AudiFactory类源码:

public class AudiFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new Audi();
    }
}

新增BMWFactory类源码:

public class BWMFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new BMW();
    }
}

Client.java源码如下:

public class Client {
    public static void main(String[] args) {
        AudiFactory audiFactory = new AudiFactory();
        BWMFactory bwmFactory = new BWMFactory();
        Car car1 = audiFactory.createCar();
        Car car2 = bwmFactory.createCar();
        car1.run();
        car2.run();
    }
}

控制台输出:

Audi run...
BMW run...

工厂方法模式更加符合开闭原则。弊端是每次扩展都会增加新的类。

3、抽象工厂

1)用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)。
2)抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

抽象工厂和工厂方法的模式基本一样,区别在于,工厂方法是生产一个具体的产品,而抽象工厂可以用来生产一组相同,有相对关系的产品;重点在于一组,一批,一系列;举个例子,假如生产小米手机,小米手机有很多系列,小米note、红米note等;假如小米note生产需要的配件有825的处理器,6英寸屏幕,而红米只需要650的处理器和5寸的屏幕就可以了;用抽象工厂来实现:

Cpu源码:

public interface Cpu {
    void run();

    class Cpu650 implements Cpu {

        @Override
        public void run() {
            System.out.println("这是Cpu650在跑...");
        }
    }

    class Cpu825 implements Cpu {

        @Override
        public void run() {
            System.out.println("这是Cpu825在跑...");
        }
    }
}

Screen源码:

public interface Screen {
    void size();

    class Screen5 implements Screen {

        @Override
        public void size() {
            System.out.println("这是5寸显示屏...");
        }
    }

    class Screen6 implements Screen {

        @Override
        public void size() {
            System.out.println("这是6寸显示屏...");
        }
    }
}

PhoneFactory 源码:

public interface PhoneFactory {

    Cpu getCpu();

    Screen getScreen();

}

XiaoMiFactory源码:

public class XiaoMiFactory implements PhoneFactory {
    @Override
    public Cpu getCpu() {
        return new Cpu.Cpu825();
    }

    @Override
    public Screen getScreen() {
        return new Screen.Screen6();
    }

}

RedMiFactory源码:

public class RedMiFactory implements PhoneFactory {
    @Override
    public Cpu getCpu() {
        return new Cpu.Cpu650();
    }

    @Override
    public Screen getScreen() {
        return new Screen.Screen5();
    }
}

Client源码:

public class Client {
    public static void main(String[] args) {
        XiaoMiFactory factory = new XiaoMiFactory();
        factory.getCpu().run();
        factory.getScreen().size();

        RedMiFactory redMiFactory = new RedMiFactory();
        redMiFactory.getCpu().run();
        redMiFactory.getScreen().size();
    }
}

控制台输出:

这是Cpu825在跑...
这是6寸显示屏...
这是Cpu650在跑...
这是5寸显示屏...

如果小米手机出了845的CPU则只需新增Cpu845实现Cpu接口方法,然后在XiaoMiFactory工厂里面返回Cpu.Cpu845()即可。

参考文章:
https://www.jianshu.com/p/33f9301fb8fe

总结:

  1. 工厂设计模式分为三类。简单工厂,工厂方法,抽象工厂。
  2. 三种模式没有高下之分。
  3. 简单工厂模式适合用于项目需求简单,产品很少并且几乎没有扩展可能性的情况。
  4. 工厂方法模式适合用于产品簇单一,但却经常发生改变的情况。
  5. 抽象工厂适合用于项目拥有多个产品簇,且产品等级经常发生改变,并且还需要尽可能控制项目体积的情况。
  6. 笔者倾向于简单工厂方法>抽象工厂模式>工厂方法模式的思考方式。原因在于简单的问题用简单工厂方法已经足够,而稍微复杂的问题则几乎会面临扩展和工厂类大量增多的情况,用抽象工厂模式更能有效的解决问题。

END.

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

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,734评论 0 14
  • 文章部分内容转载自:http://blog.csdn.net/zhangerqing 一、设计模式的分类 总体来说...
    j_cong阅读 2,055评论 0 20
  • 男女大不同,虽然刻意去分类男女,是不太合适的,可也不是完全没有道理。 1 男人是理性动物,女人是感性动物 女人的思...
    大晶cleo阅读 331评论 1 2
  • https://link.zhihu.com/?target=http%3A//audiocdn.economis...
    毛君阅读 2,056评论 0 0
  • 吃完晚饭六点半,开始了与孩子因为吃药而引发的拉锯战,直到十点这场战役才收宫!60毫升的中药,三个半小时的折磨。我都...
    那山那水那一片天阅读 257评论 0 0