简单工厂模式&工厂方法模式&抽象工厂模式

简单工厂模式

先来看一个问题,我们要给手机买一个手机壳,因为各种手机形状不一致,所以手机壳有很多种类,下面用代码的形式处理这个问题

String phoneName = "xxx";
// 所有的shell都是继承自PhoneShell,这里偷个懒就不写了。
PhoneShell shell = null;
if("Iphone".equals(phoneName)){
    shell = new IphoneShell();
}else if("huawei".equals(phoneName)){
    shell = new HuaweiShell();
}....

在这个例子的代码实现里,我们用到了很多的if else,不是说不能用if else 但是过多的if else堆砌会显得代码不是那么的简洁,这时我们把这些判断逻辑封装起来

public class PhoneShellFactory{
    public static PhoneShell getPhoneShell(String phoneName){
        if("Iphone".equals(phoneName)){
            return new IphoneShell();
        }else if("huawei".equals(phoneName)){
            return new HuaweiShell();
        }...
    }
}

再次编写解决这个问题的代码,代码就成了下面这个样子

String phoneName = "xxx";
PhoneShell shell = PhoneShellFactory.getPhoneShell(phoneName);

代码就变得十分简洁了,但是还是有问题,虽然原本的if else没了,但是我们在编写PhoneShellFactory这个类的时候还是写了if else啊,这不是自欺欺人吗?复杂度不会消失,只会转移,所以我们把根据手机类型获得手机壳的过程封装在一个类之中,这像不像你去手机店买手机壳,只需要告诉店家你的手机类型,店家就会给你找来合适的手机壳,而不是你自己挨个去找,这就是简单工厂模式,也叫做静态工厂模式,因为只有一个获得商品的静态方法,所以没必要每次都实例化工厂对象,简单工厂模式是有违开闭原则的,开闭原则简单来说就是,允许对代码进行扩展,但是不允许对原有的代码进行修改,所以如果我们要增加商店提供的手机壳的种类就要修改PhoneShellFactory的代码,这就有违开闭原则。简单工厂模式也并不是每次都要创建新的对象,也可以在代码逻辑里加入缓存,这里就不作赘述。

工厂方法模式

前面说的简单工厂方法是有违开闭原则的,相反的,工厂方法模式是不违背开闭原则的,但是工厂方法并不是简单工厂的进阶版本,他俩的着重点是有区别的,首先我们定义一个ShellFactory接口

public interface ShellFactory {
    public PhoneShell getShell();
}

接下来我们定义两个实现ShellFactory的类

public class IphoneShellFactory extends ShellFactory {
    @Override
    public PhoneShell getShell() {
        return new IphoneShell();
    }
}

public class HuaweiShellFactory extends ShellFactory {
    @Override
    public PhoneShell getShell() {
        return new HuaweiShell();
    }
}

下面我们编写购买手机壳的代码

ShellFactory sf = new IphoneShellFactory();
PhoneShell shell = sf.getShell();

类图如下

工厂模式满足了开闭原则,如果我们需要增加一个手机壳的种类,只需要编写一个实现ShellFactory的类即可,但是如果想要根据传入的手机类型创建手机壳工厂,还是需要if else逻辑判断,所以前面说工厂方法并不是简单工厂的进阶版本,他俩的着重点是有区别的,看完上面的代码可能会有一个疑问,既然都知道是要iphone的手机壳那我们直接new 一个IphoneShell不就行了,还用整这么麻烦吗?还要先new 一个IphoneShellFactory然后调用getShell才能得到IphoneShell简直不要太复杂,其实上面的代码只是简单的说明了工厂方法模式满足了开闭原则,工厂方法模式的着重点其实是隐藏创建产品的细节,且不一定每次都会真正创建产品,还是用代码来说,我们来一个实现ShellFactory的类

public class XiaomiShellFactory implements ShellFactory {
    @Override
    public PhoneShell getShell() {
        PhoneShell shell = new XiaomiShell();
        shell.rePrint(); // 手机壳重新喷涂颜色;
        return shell;
    }
}

这里我们在getShell方法里,加了一点细节,在实际的业务中可能创建一个产品对象有很多的细节操作,工厂方法模式的意义就是隐藏这些细节,再举一个简单的例子,比如我们买手机,同一款手机会有很多可变的参数,比如颜色,RAM,ROM,

public class Mi10Blue6$256PhoneFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        Phone phone = new Mi10();
        phone.printColor("Blue");
        phone.setRAM(6);
        phone.setROM(256);
        return phone
    }
}

当然这个例子还是有点单薄,操作比较简单,也可以用构造函数实现,这里只是理解一下思想,不必较真,真实的业务里可能不仅仅是对POJO属性的简单操作。那不一定每次都会真正创建产品又是什么意思呢,还是用代码来说

public class XiaomiShellFactory implements ShellFactory {
    static Stack stack = new Stack();
    static{
        // 柜台上一开始可能就摆放着一些手机壳,可能是热卖的,也可能是拿给别的顾客看,顾客没买的。
        // 从仓库取手机壳相当于创建一个新的手机壳, 从柜台获取相当于没有新创建一个
        stack.push(new XiaomiShell());
    }
    @Override
    public PhoneShell getShell() {
        if(stack.isEmpty()){
            return new XiaomiShell();
        }else{
            return (PhoneShell) stack.pop();
        }
    }
}

这里对应到实际的业务中可能就是相应的缓存。

抽象工厂

工厂方法模式只是生产一个对象也就是一个产品,有时业务特别复杂,需要一个工厂得到多个产品怎么办?这时候就该抽象工厂出场了,从工厂方法模式来理解,一个工厂能创建一类产品,如果需要创建多类产品,那就是需要创建工厂的工厂,下面上代码,首先创建接口ElectronicsmakersFactory

public interface ElectronicsmakersFactory{
    public Phone getPhone();
    public Computer getComputer();
}

接着创建实现类

public XiaoMiFactory implements ElectronicsmakersFactory{
    @Override
    public Phone getPhone() {
        return new Mi10PhoneFactory.getPhone();
    }
    @Override
    public Computer getComputer() {
        return new MiBookComputerFactory.getComputer();
    }
}

public AppleFactory implements ElectronicsmakersFactory{
    @Override
    public Phone getPhone() {
        return new Ip11PhoneFactory.getPhone();
    }
    @Override
    public Computer getComputer() {
        return new MacBookProComputerFactory.getComputer();
    }
}

调用时的代码

ElectronicsmakersFactory ef = new XiaoMiFactory();
Phone phone = ef.getPhone();
Computer computer = ef.getComputer();

类图如下

总结

简单工厂模式主要注重于隐藏处理逻辑,工厂方法模式注重于隐藏装配类的细节,抽象工厂模式主要是处理复杂的业务逻辑,层级比较多。

猜你喜欢

转载自www.cnblogs.com/ljsh/p/12636251.html