工厂模式

静态工厂
在最早的《DesignPattern》这本书中 静态工厂是没有的 工厂系列就两个模式 工厂方法和抽象工厂,但是也有人说静态工厂是工厂模式

什么是工厂?
1.任何可以产生(new)对象的方法或类,都可以称之为工厂
2.看到1个方法 它的返回值return是1个对象 就可以称之为1个工厂

所以单例也是一种工厂,单例模式的 getInstance 就是拿到1个对象 所以有人把单例模式 称为静态工厂

为什么要工厂? 我们已经可以new产生对象了,为什么还要工厂?
工厂可以灵活控制生产过程,可以加权限、修饰decorate、日志log等

我们先写1个类 Car

public class Car {
    public void go() {
        System.out.println("Car go wuwuwuwuwu.....");
    }
}

然后我们再创建1个Main类 new出来1个Car

public class Main {
    public static void main(String[] args) {
        Car c = new Car();
        c.go();
    }
}
执行main方法

现在开的是Car车 我明天想开Plane飞机怎么办? 可以定制交通工具(实现类 )吗?
我们当然可以再创建1个Plane飞机类,然后main方法去创建1个飞机

public class Plane {
    public void go(){
        System.out.println("Plane fly xixixixixixixi....");
    }
}
public class Main {
    public static void main(String[] args) {
//        Car c = new Car();
//        c.go();
        Plane p = new Plane();
        p.go();
    }
}

如果我以后想开火车Train,船Boat等等?难道还是像这样 1个1个扩展吗?代码太多了,既要新建1个类,还要修改main方法里的内容,我想少点,怎么办?
我们可以创建1个接口Moveable ,其他的所有交通工具去实现这个接口

public interface Moveable {
    void go();
}
public class Plane implements Moveable{
    public void go(){
        System.out.println("Plane fly xixixixixixixi....");
    }
}
public class Car implements Moveable{
    public void go() {
        System.out.println("Car go wuwuwuwuwu.....");
    }
}

这样main方法可以利用多态,只用改new后面的类就行了,不管调用

public class Main {
    public static void main(String[] args) {
        Moveable m = new Plane();
        m.go();
    }
}

代码只用修改1个地方,不用像第1种方法,要删除修改至少2段

需求又来了,我想任意定制旅途过程 怎么办?
实际中的应用 我new 1个交通工具后 我要求你必须控制权限 那么我的代码要修改在Plane类里 必须要来回的变;我可以把 产生对象的这个过程 不用new 我交给1个工厂方法
1.简单工厂VehicleFatory
创建1个VehicleFactory类 里面有几个方法 比如返回Car对象的 createCar()方法 在这个方法里面 我们可以对它进行日志处理 权限处理等;而且VehicleFactory类除了 产生Car外 还可以产生Plane等

public class VehicleFactory {
    public Car createCar(){
        return new Car();
    }
    public Plane createPlane(){
        return new Plane();
    }
}

但是这种方法不太好 因为它虽然很简单 但是可扩展性不太好 当我们新添加1种交通工具 火车train的时候 里面就要新添加新的createTrain方法 而且里面的 权限处理的操作也是写死的

针对每个产品做1个工厂
对于Car来说 我加1个CarFactory类

public class CarFactory {
    public Car createCar(){
        System.out.println("a car created!");
        return new Car();
    }
}

如果我们想用CarFactory的话 main方法要这样写

public class Main {
    public static void main(String[] args) {
        Moveable m = new CarFactory().createCar();
        m.go();
    }
}
简单工厂

想来个Plane的话 就写个PlaneFactory().createPlane() 想来个broom的话 就写个BroomFactory().createBroom()
但是问题来了 当我们要添加一种新的交通工具的时候 我们首先得把它的工厂做出来PlaneFactory,broomFactory 接下来 我还要把代码改一下 更麻烦
总结一下:任意定制交通工具,我们可以 继承Moveable;任意定制生产过程,我们可以Moveable XXXFactory.create()

2.抽象工厂
因为叫抽象工厂,所以是任意定制产品一族(不只1种系列产品),叫abstractFactory 更加抽象这个问题。
比如:现在是这样的 ,作为1个司机 我开着一辆车 车还在跑,然后这个司机,他手里还持有1个武器AK47 就叫AK47类,他还可以吃一点面包Bread 有个面包类
AK47类可以开枪,Brand类可以打印品牌

public class AK47 {
    public void shoot(){
        System.out.println("tutututututu.....");
    }
}

public class Brand {
    public void printName(){
        System.out.println("wdm");
    }
}

那么这样我就模拟了 很多类产品 Car,AK47,Bread ,其实这个是 产品簇的概念 我们有没有一种方式 可以灵活的指定 来扩展新的产品簇,比如现在我来一个人是魔法师 他骑的是扫帚Broom 吃的是蘑菇Mushroom 它的魔法棒MagicStick可以发电 这样当新的产品加进来的时候 代码不用改太多呢?
可以的 我们可以new 1个AbstractFactory. 这个抽象工厂 可以生产 1系列产品 他可以生产食物,武器,交通工具

public abstract class Food {
    abstract void printName();
}

public abstract class Weapon {
    abstract void shoot();
}

public abstract class Vehicle {
    abstract void go();
}

我们假设 这个抽象工厂会产生 3类产品;第1类是Food,第2类是Vehicle,第3类是Weapon,他们都可以返回对应的对象,可以生成抽象的产品

public abstract class AbstractFactory {
    abstract Food createFood();
    abstract Vehicle createVehicle();
    abstract Weapon createWeapon();
}

然后我们让所有的不同类别的产品 去继承
现代人的工具簇就是 Weapon对应AK47,Food对应Bread,Vehicle对应Car

//现代人的工具包
public class Car extends Vehicle{
    public void go() {
        System.out.println("Car go wuwuwuwuwu.....");
    }
}

public class Brand extends Food{
    public void printName(){
        System.out.println("wdm");
    }
}

public class AK47 extends Weapon{
    public void shoot(){
        System.out.println("tutututututu.....");
    }
}

我们做1个现代工厂ModernFactory,帮我们去生产这些东西,而不必自己去new

public class ModernFactory extends AbstractFactory {
    @Override
    Food createFood() {
        return new Brand();
    }
    @Override
    Vehicle createVehicle() {
        return new Car();
    }
    @Override
    Weapon createWeapon() {
        return new AK47();
    }
}

魔法师的工具簇就是 Weapon对应MagStick,Food对应MushRoom,Vehicle对应Broom

//魔法师的工具包
public class Broom extends Vehicle {
    public void go(){
        System.out.println("Broom flying shushushus....");
    }
}

public class MushRoom extends Food {
    public void printName(){
        System.out.println("毒蘑菇");
    }
}

public class MagicStick extends Weapon{
    public void shoot(){
        System.out.println("dian dian dian dian....");
    }
}

魔法师就是魔法工厂MagicFactory,帮我们去生产这些东西

public class MagicFactory extends AbstractFactory{
    @Override
    Food createFood() {
        return new MushRoom();
    }
    @Override
    Vehicle createVehicle() {
        return new Broom();
    }
    @Override
    Weapon createWeapon() {
        return new MagicStick();
    }
}

现在,我们main方法里面代码就简单了
之间我们需要1个1个new

        Car c =new Car();
        c.go();
        AK47 w=new AK47();
        w.shoot();
        Bread b=new Bread();
        b.printName();

现在不需要了 直接调用现代工厂里的方法就行

AbstractFactory f = new ModernFactory();
Vehicle c = f.createVehicle();
Weapon w = f.createWeapon();
Food  b = f.createFood();

而且修改代码恨少,你想改成 魔法世界工厂 你就把new 后面改一下 下面的都不用改 new MagicFactory(),同理,火星世界 就改成火星一簇 写个MarsFactory 去实现里面的火星武器,食物,机器

注意:这个工厂里用的都是继承,不是接口的实现,因为工厂里的产生的食品一般是现实中存在的,但是它不是具体的某个食物,所以用抽象类比较合适,而接口更加侧重于这个东西的属性,moveable表示它这个东西可以动,comparable表示这个东西可以比较,所以从语义上用抽象类更加合适,形容词用接口,名词用抽象类

比较 工厂方法 和抽象工厂
工厂方法:在产品扩展时,比较方便
有Car 有Food 有AK47 以后比如说 还有帽子等等 非常方便


普通工厂

抽象工厂:然后 在产品簇上扩展比较方便 但是在产品上扩展不好扩展


抽象工厂

所以这个是两个维度上的扩展,1个是产品一簇维度上 偏于扩展; 另一个是产品单一维度上 好扩展 都有自己的局限性

总结一下:
简单工厂vs静态工厂vs工厂方法vs抽象工厂
简单工厂:我们随便1个方法 只要createCar什么东西 返回的是1个对象 那么它就是简单工厂
静态工厂:静态的方法Static产生 比如单例的getInstance 就是1个静态工厂
工厂方法FactoryMethod:产品维度上扩展 很方便
抽象工厂:产品一簇进行扩展

我们经常可以用抽象工厂来完成一键风格替换,比如1个人物,我可以换它的声音,皮肤,动作等

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

推荐阅读更多精彩内容