设计模式-工厂模式

工厂模式主要分为 3 类:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工程模式>

在讲解这三种设计模式之前,问大家一个问题:我们平常写代码的时候,对象是怎么创建的呢?

大家都知道的,直接 new 一个对象呗,比如 Class a = new Class();

没错,在大多数情况下,直接使用 new 关键字来创建对象没有问题,但有没有想过,如果创建对象需要一系列复杂的初始化操作,别人需要关联其他成员对象、查配置文件或者数据库,这时候怎么办呢?

这个时候,我们可以增加一个特殊的类–工厂类,专门负责对象的创建工作

工厂模式的主要解决的问题是,将原来分布在各个地方的对象创建过程单独抽离出来,交给工厂类负责创建。其他地方想要使用对象直接找工厂(即调用工厂的方法)获取对象。

今天就来讲讲这三种模式来举例了解一下

简单工厂模式

假设我们已领养宠物狗(dog)为例,这个类实例需要在许多地方被创建和初始化,而初始化的代码也比较复杂。

public class KejiDog {
    //构造函数
    public KejiDog(){
        // .....
    }
}

针对这种情况,我们可以构建一个狗店(工厂)专门负责创建狗对象,把柯基的初始化代码迁移到工厂类的创建方法当中:

public class kejiDogFactory {

    public Mask createKejiDog() {
        KejiDog kejiDog = new KejiDog();
        // .....
        return kejiDog;
    }
}

那么,如果店(工厂)中不只存在柯基呢,如果也有巴哥呢,那么该如何来创建对象呢?这时候我们可以给店(工厂)添加一系列的判断。

假设狗的类只是一个抽象接口,有两个子类“柯基”和“巴哥”分别实现了以下接口:

public interface DogShop {
    void show();
}

public class Keji implements DogShop {
    @Override
    public void show() {
        System.out.println("我是柯基");
    }
}

public class Bage implements DogShop {
    @Override
    public void show(){
        System.out.println("我是巴哥");
    }

}

那么店(工厂)该如何创建这两种类型的宠物狗呢?

很简单,在创建方法中传入参数(这里的参数是type),根据参数来做条件判断,决定创建什么样的宠物狗:

public class DogShopFactory{

    public DogShop createDog(String type) {
        DogShop dogShop = null;
        if("柯基".equals(type)){
            dogShop = new Keji();
            // .....
            // HighEndMask的100行初始化代码
        }else if("巴哥".equals(type)){
            dogShop =  new Bage();
            // .....
            // LowEndMask的100行初始化代码
        }
        return dogShop;
    }
}

最后想要创建什么样狗的对象,只需传入对应的类型名称即可,如下:

public class Test {

    public static void main(String[] args) {
        DogShopFactory factory = new DogShopFactory();
        DogShop maskA = factory.createDog("柯基");
        DogShop maskB = factory.createDog("巴哥");
        maskA.show();
        maskB.show();
    }
}

通过工程类创建对象,并且传入参数决定具体类对象的做法,就是简单工厂模式

但是有一个问题不知道大家发现没有?

如果增加不同狗的类型,店(工厂)的创建方法中就要增加新的if-else判断,这种方式并不符合面向对象的开放/封闭原则吧

注:所谓面向对象的开放-封闭原则,就是在程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要增加新的if-else,就涉及对旧有代码的修改,不但容易出错,可读性也不好。

这里想要解决if-else的问题,可以为每一个狗类创建对应的工厂子类,这些工厂子类分别实现抽象的工厂接口,这样的话,只要我们实例化不同的工厂子类,调用创建方法,得到的就是对应狗的对象。

工厂方法模式

public interface DogShopFactory {
    IMask createMask();
}

public class KejiFactory implements DogShopFactory{

    @Override
    public DogShop createMask() {
        DogShop mask =  new Keji();
        // .....
        return mask;
    }
}

public class BageFactory implements DogShopFactory{

    @Override
    public DogShop createMask() {
        DogShop mask =  new Bage();
        // .....
        return mask;
    }
}

在代码中,工厂类变成了抽象的接口,柯基工厂和巴哥工厂这两个子类分别实现了该接口。

想要创建什么样的口罩对象,只需实例化不同的工厂子类,调用相同的创建方法,无需再传入参数。

public class Test {

    public static void main(String[] args) {
        KejiFactory factoryA = new KejiFactory();
        BageFactory factoryB = new BageFactory();
        DogShop maskA = factoryA.createMask();
        DogShop maskB = factoryB.createMask();
        maskA.show();
        maskB.show();
    }
}

到这里的话又有一个问题了:如果需要创建的子类越来越多,不只是有狗,也有猫的话,难道每个子类都要对应一个工厂类吗

在抽象工厂模式当中这个问题得到了很好的解决

抽象工厂模式

在这里插入图片描述
狗和猫是两个抽象接口,分别拥有贵和不贵两个实现类:

public interface Dog {
    void showMask();
}

public class NotExpensiveDog implements Dog {
    @Override
    public void showMask(){
        System.out.println("不贵的狗");
    }
}

public class ExpensiveDog implements IMask {
    @Override
    public void showMask() {
        System.out.println("贵的狗");
    }
}

public interface Cat {
    void showSuit();
}

public class NotExpensiveCat implements Cat {
    @Override
    public void showSuit() {
        System.out.println("不贵的猫");
    }
}

public class ExpensiveCat implements Cat {
    @Override
    public void showSuit() {
        System.out.println("贵的猫");
    }
}

接下来是工厂类,由于动物分成了贵和不贵两大组,工厂也相应分成了贵工厂和不贵工厂,各自负责自己的的创建:

public interface IFactory {
    IMask createMask();
    IProtectiveSuit createSuit();
}

public class NotExpensiveFactory implements IFactory {
    @Override
    public Dog createMask() {
        Dog dog =  new NotExpensiveDog();
        // .....
        return dog;
    }

    @Override
    public IProtectiveSuit createSuit() {
        Cat cat =  new NotExpensiveCat();
        // .....
        return cat;
    }
}

public class ExpensiveFactory implements IFactory {
    @Override
    public IMask createMask() {
        Dog dog =  new ExpensiveDog();
        // .....
        return dog;
    }

    @Override
    public IProtectiveSuit createSuit() {
        Cat cat =  new ExpensiveCat();
        // .....
        return cat;
    }
}

通过实例化不同的工厂子类,调用不同的创建方法,可以创建出不同的产品。

public class Test {

    public static void main(String[] args) {
        IFactory factoryA = new NotExpensiveFactory();
        IFactory factoryB = new ExpensiveFactory();
        //创建不贵的狗
        Dog maskA = factoryA.createMask();
        //创建贵的狗
        Dog maskB = factoryB.createMask();
        //创建不贵的猫
        Cat suitA = factoryA.createSuit();
        //创建贵的猫
        Cat suitB = factoryB.createSuit();

        maskA.showMask();
        maskB.showMask();
        suitA.showSuit();
        suitB.showSuit();
    }
}

最后

这里有个问题,到底什么时候该用工厂方法模式,而非简单工厂模式呢?

当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。

而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值