工厂模式

静态工厂
在最早的《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个人物,我可以换它的声音,皮肤,动作等

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容