zoukankan      html  css  js  c++  java
  • 简单工厂模式&工厂方法模式&抽象工厂模式

    简单工厂模式

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

    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();
    

    类图如下

    总结

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

  • 相关阅读:
    币值转换
    第八周作业
    第七周作业
    第五周编程总结
    第四周编程总结
    第三周编程总结
    7-1 查找整数
    7-2 求最大值及其下标
    秋季学习总结
    对我影响最大的三个老师
  • 原文地址:https://www.cnblogs.com/ljsh/p/12636251.html
Copyright © 2011-2022 走看看