Java设计模式之工厂模式

国际惯例,扯闲篇

今天阴天,很开心,前几天的大太阳晒得我更黑了~~~

面向对象设计的基本原则

OCP(开闭原则):一个软件的实体应当对扩展开发,对修改关闭。对于已完成的类,尽可能地不要去修改其内容

DIP(依赖倒转原则):要针对接口编程,不要针对实现编程。这样会让代码更易读,不会经常写着写着就晕头转向

Lod(迪米特法则):只与你直接的朋友通信,避免和陌生人通信。

设计模式也好,基本原则也罢,都应该揉进平时的工作中去思考,用它们来指导完成代码的设计,书写

核心本质

  • 实例化对象,用工厂方法代替new操作
  • 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦

工厂模式分类

  • 简单工厂模式:用来修改同一等级结构中的产品(对于增加新的产品,需要修改已有代码)

  • 工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)

  • 抽象工厂模式:用来生产不同产品族的全部产品(对于增加新的产品无能无力,支持增加新的产品族)

Talk is cheap,show me the code!!!

简单工厂模式

遵循前面介绍的基本原则,我们先新建一个Car接口,给一个run方法

public interface Car {
    void run();
}

接着,新建两个实现该接口的类:Audi,Benz

public class Audi implements Car {
    @Override
    public void run() {
        Log.d("", "奥迪run: ");
    }
}
public class Benzi implements Car {
    @Override
    public void run() {
        Log.d("", "奔驰run: ");
    }
}

现在,再创建一个调用者Client,来调用它们的run方法。

在没有使用简单工厂模式的情况下,这样写:

public class Client {

    Car myCar = new Audi();
    
    private void test() {
        myCar.run();
    }

}

这样写显然没有什么错,清晰明了,但是,我们的调用者Client却需要知道Audi这个类名,还需要知道它的构造方法去new出这个对象,当Audi这个类的构造方法比较复杂的时候,就要传很多参数,对我们的调用者来说,显然是十分麻烦的,我们只是想调用一下run方法而已。

那么,当使用了简单工厂模式后,写法如下:

public class CarFactory {

    private Car createCar(String type) {
        switch (type) {

            case "奥迪":
                return new Audi();
                //就别break了,都return了

            case "奔驰":
                return new Benzi();

            default:
                break;
        }
        return null;
    }
}

此时,当我们再想调用Audi的run方法,只需跟CarFactory打交道即可,至于CarFactory内部,到底经历多复杂的过程,才把这个Audi构造出来,我们调用者不想管,也不用管。

缺点
或许你已经注意到了,简单工厂方法模式显然违反了一开始就提到的OCP开闭原则,当我们想要创建一个比亚迪呢?显然是要在createCar方法里进行修改,再加一个case “比亚迪”:

case "比亚迪"
     return new BYD();

简单工厂模式也被称为静态工厂模式,因为工厂类一般是使用静态方法,方便调用。当然了,上面只是示意写法,看懂意思就好,别较真。

工厂方法模式

上面提到了简单工厂模式,违背了开闭原则,使用工厂方法模式就可以解决掉这个问题(尽管如此,还是简单工厂模式用的最多)

怎么写呢?
Audi还是那个Audi,Benz还是那个Benz,Car还是那个Car,具体写法如下(以调Audi的run为例):

/**
 * 新增一个CarFactory
 */
public interface CarFactory {

    Car createCar();
}

当我们想调Audi的run的时候,就新增一个AudiFactory,实现CarFactory接口:

public class AudiFactory implements CarFactory{

    @Override
    public Car createCar() {
        return new Audi();
    }
}

那么调用者的写法就变成了:

public class Client {

    private void test() {
        Car audi = new AudiFactory().createCar();
        audi.run();
    }
}

此时,我们再想增加一个比亚迪的话,就再写一个BYDFactory类,而不用去修改已有的代码了。

虽然工厂方法模式贴合了开闭原则,却多写了很多个类,每增加一个新的产品就要多一个Factory。

选择:
理论上,工厂方法模式占优,实际上,选择简单工厂模式居多。

抽象工厂模式

  • 用来生产不用产品族的产品
  • 工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式生产需要的对象是一种非常好的解决方式

场景模拟:

在上文中,我们只创建一个Car接口,需求是生产该接口下的实现类对象,如果现在的接口变多了,需求变成生产多个接口下的子类对象呢?

定义一个Engine接口,两个实现该接口不同类:GoodEngine,BadEngine

public interface Engine {

    void run();

    void start();
}

//好发动机
class GoodEngine implements Engine {

    @Override
    public void run() {
        Log.d("", "转得快");
    }

    @Override
    public void start() {
        Log.d("", "启动快 ");
    }
}

//差发动机
class BadEngine implements Engine{

    @Override
    public void run() {
        Log.d("", "转得慢");
    }

    @Override
    public void start() {
        Log.d("", "启动慢");
    }
}

再定义一个Seat接口,两个实现该接口的不同类:GoodSeat,BadSeat

public interface Seat {

    void massage();
}

class GoodSeat implements Seat{

    @Override
    public void massage() {
        Log.d("", "可以按摩");
    }
}

class BadSeat implements Seat{

    @Override
    public void massage() {
        Log.d("", "不能按摩");
    }
}

定义一个CarFactory接口

public interface CarFactory {

    Engine createEngine();

    Seat createSeat();

}

定义两个实现该接口的不同工厂类,来生产不同的产品族

public class BadCarFactory implements CarFactory {
    @Override
    public Engine createEngine() {
        return new BadEngine();
    }

    @Override
    public Seat createSeat() {
        return new BadSeat();
    }

}

public class GoodCarFactory implements CarFactory {

    @Override
    public Engine createEngine() {
        return new GoodEngine();
    }

    @Override
    public Seat createSeat() {
        return new GoodSeat();
    }

}

结语:

上一次的文章,回过头来看,好短小,与我本人不贴切,所以这次的文章,夹杂了不少自己的废话,万望海涵,错误的地方还请大家帮忙指正,多谢!!!拜拜~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值