设计模式之工厂模式

为什么需要工厂

我们来看看,当没有工厂时引发的问题

业务情景,当前有许多卖手机的店,里面卖着各种型号的手机,当前卖了苹果,三星,oppo,三款手机

当前设计

这里写图片描述
对应代码

IPhone

package headfirst.hd.factory.phone;

public class IPhone {
    public double price = 6000;
}

Samsung

package headfirst.hd.factory.phone;

public class Samsung{
    public double price = 5000;
}

Oppo

package headfirst.hd.factory.phone;

public class Oppo{
    public double price = 2888;
}

PhoneStore ,当前需要卖一个IPhone手机

package headfirst.hd.factory.phone;

public class PhoneStore {
    public void salePhone() {
        IPhone iPhone = new IPhone();
        System.out.println(iPhone.price);
    }
}

测试类
Client

package headfirst.hd.factory.phone;

public class Client {

    public static void main(String[] args) {
        PhoneStore phoneStore = new PhoneStore();
        phoneStore.salePhone();
    }

}
问题来了

当我们需要卖其他手机的时候,我们需要修改PhoneStore类,如下当我们需要卖Oppo手机时

package headfirst.hd.factory.phone;

public class PhoneStore {
    public void salePhone() {
        Oppo oppo= new Oppo();
        System.out.println(oppo.price);
    }
}

引入简单工厂

为了解决以上问题,我们引入简单工厂,通过接收的参数的不同来返回不同的对象实例。

简单工厂模型

这里写图片描述

重写设计模型

我们将手机抽象成接口,使用工厂类有一个共同的产品类型

设计为

这里写图片描述

重要代码为,以下修改

package headfirst.hd.factory.phone;

public interface Phone {
    void salePrice();
}

package headfirst.hd.factory.phone;

public class IPhone implements Phone {
    public double price = 6000;

    @Override
    public void salePrice() {
        System.out.println(price);
    }

}

package headfirst.hd.factory.phone;

public class Oppo implements Phone {
    public double price = 2888;

    @Override
    public void salePrice() {
        System.out.println(price);
    }
}

package headfirst.hd.factory.phone;

public class Samsung  implements Phone {
    public double price = 5000;

    @Override
    public void salePrice() {
        System.out.println(price);
    }
}

package headfirst.hd.factory.phone;

public class SimpleFactory {

    enum PhoneType {
        IPHONE,OPPO,SAMSUNG
    }

    public Phone createProduct(PhoneType type) {

        Phone phone = null;
        if (PhoneType.IPHONE == type) {
            phone = new IPhone();
        } else if (PhoneType.OPPO == type) {
            phone = new Oppo();
        } else if (PhoneType.SAMSUNG == type) {
            phone = new Samsung();
        }

        return phone;
    }


}

package headfirst.hd.factory.phone;

import headfirst.hd.factory.phone.SimpleFactory.PhoneType;

public class PhoneStore {

    SimpleFactory simpleFactory;

    public PhoneStore(SimpleFactory simpleFactory) {
        this.simpleFactory = simpleFactory;
    }

    public void salePhone(PhoneType type) {

        if (simpleFactory == null) {
            throw new NullPointerException("simpleFactory未初始化!!!");
        }

        Phone phone = simpleFactory.createProduct(type);
        phone.salePrice();
    }
}

package headfirst.hd.factory.phone;

import headfirst.hd.factory.phone.SimpleFactory.PhoneType;

public class Client {

    public static void main(String[] args) {

        SimpleFactory factory = new SimpleFactory();
        PhoneStore phoneStore = new PhoneStore(factory);
        phoneStore.salePhone(PhoneType.IPHONE);
    }

}

可以看到,简单工厂将创建实例统一管理起来,这是他的优点

缺点是当我们需要新增一种类型,必须打开createProduct方法,如下,我们添加XiaoMi手机类型

新增手机类型,小米XiaoMi


package headfirst.hd.factory.phone;
public class XiaoMi implements Phone {
    public double price = 1999;

    @Override
    public void salePrice() {
        System.out.println(price);
    }
}

修改SimpleFactory

package headfirst.hd.factory.phone;

public class SimpleFactory {

    enum PhoneType {
        IPHONE,OPPO,SAMSUNG,XIAOMI
    }

    public Phone createProduct(PhoneType type) {

        Phone phone = null;
        if (PhoneType.IPHONE == type) {
            phone = new IPhone();
        } else if (PhoneType.OPPO == type) {
            phone = new Oppo();
        } else if (PhoneType.SAMSUNG == type) {
            phone = new Samsung();
        } else if (PhoneType.XIAOMI == type) {
            phone = new XiaoMi();
        }

        return phone;
    }


}

PS:简单工厂不是设计模式

引入工厂方法模式

为了解决以上问题,我们引入工厂方法模式,通过逻辑拆分,将创建实例封装在不同的工厂中,例如,IPhone有很多款手机,XiaoMi也有很多款手机,当IPhone发布新手机的时候,我们需要改变IPhone对应的工厂

工厂方法模式模型

这里写图片描述

重写设计新模型

这里写图片描述

这里只贴与factory相关的代码,重点说明一下工厂方法模式
PhoneFactory

package headfirst.hd.factory.phone;

public abstract class PhoneFactory {
    //父类定义抽象接口,不管子类具体是哪一种类型
    public void salePhone(String type) {
        Phone phone = createProduct(type);
        phone.salePrice();
    }

    //子类只实现这个方法,其他的什么都不做
    protected abstract Phone createProduct(String type);
}

XiaoMiPhoneFactory

package headfirst.hd.factory.phone;

public class XiaoMiPhoneFactory extends PhoneFactory {

    @Override
    protected Phone createProduct(String type) {

        Phone phone = null;

        if ("XiaoMi2".equals(type)) {
            phone = new XiaoMi2();
        } else if ("XiaoMi3".equals(type)) {
            phone = new XiaoMi3();
        }

        return phone;
    }

}

IPhonePhoneFactory

package headfirst.hd.factory.phone;

public class IPhonePhoneFactory extends PhoneFactory {

    @Override
    protected Phone createProduct(String type) {

        Phone phone = null;

        if ("IPhone4".equals(type)) {
            phone = new IPhone4();
        } else if ("IPhone5".equals(type)) {
            phone = new IPhone5();
        }

        return phone;
    }

}

测试Client

package headfirst.hd.factory.phone;

public class Client {

    public static void main(String[] args) {
        //卖小米4
        PhoneFactory factory = new XiaoMiPhoneFactory();
        factory.salePhone("XiaoMi2");

    }
}
重要说明


  1. 工厂方法模式,其中方法指的子类里只实现父类的抽象方法,而父亲提供产品的行为,工厂方法模式将两者解耦,使类责任单一化
  2. 与简单工厂的相似性,如果单单看其中某一个工厂,和所对应的产品,工厂方法模式和简单工厂很类似,如下图所示
    这里写图片描述
  3. 站在PhoneFactory角度看,我们将原来简单工厂的逻辑,按照业务拆分成多个方法
    这里写图片描述
  4. 当我们新增具体的产品时候
    • 当前新增手机IPhone6,简单工厂会修改SimpleFactory中的代码,工厂方法模式修改IPhonePhoneFactory中的代码,不会影响XiaoMiPhoneFactory中的代码,将影响降低
    • 当前新增手机XiaoMi4,简单工厂会修改SimpleFactory中的代码,工厂方法模式修改XiaoMiPhoneFactory中的代码,不会影响IPhonePhoneFactory中的代码,将影响降低
    • 当我们新增新类型手机,例如VIVO,单工厂会修改SimpleFactory中的代码,工厂方法模式新增VivoPhoneFactory类,不会影响到已有类,最理想的状态

简单工厂对需求已知时候,毕竟适应,产品需求经常变话时,工厂方法模式更加适应

抽象工厂模式

以上问题都是单一产品。抽象工厂是应对产品族概念的。比如说,每一款手机由屏幕,处理器,内存等组成。其中屏幕,电量,内存都对应的一类产品。那么每一个工厂创建手机的组成时候,需要创建对应组成部分。

这里的产品对应的是屏幕(很多种),电量(很多种),内存(很多种)

抽象工厂模式模型

这里写图片描述

iPhone X的手机的一些配置
这里写图片描述

当前设计
这里写图片描述

对应代码

产品家族Battery

package headfirst.hd.factory.abs;

public interface Battery {
    //这里简化,不做任何操作
}

package headfirst.hd.factory.abs;

public class Battery1 implements Battery {

}

package headfirst.hd.factory.abs;

public class Battery2 implements Battery {

}

产品家族Memory

package headfirst.hd.factory.abs;

public interface Memory {
    //这里简化,不做任何操作
}

package headfirst.hd.factory.abs;

public class Memory1 implements Memory {

}

package headfirst.hd.factory.abs;

public class Memory2 implements Memory {

}

产品家族Screen

package headfirst.hd.factory.abs;

public interface Screen {
    //这里简化,不做任何操作
}

package headfirst.hd.factory.abs;

public class Screen1 implements Screen {

}

package headfirst.hd.factory.abs;

public class Screen2 implements Screen {

}

抽象工厂

package headfirst.hd.factory.abs;

public interface IPhoneXFactory {
    Screen createScreen();
    Battery createBattery();
    Memory createMemory();
}

package headfirst.hd.factory.abs;

//普通版本,8333
public class NormalFactory implements IPhoneXFactory {

    @Override
    public Screen createScreen() {
        return new Screen1();
    }

    @Override
    public Battery createBattery() {
        return new Battery1();
    }

    @Override
    public Memory createMemory() {
        return new Memory1();
    }

}

package headfirst.hd.factory.abs;

//plus版本,10000
public class PlusFactory implements IPhoneXFactory {

    @Override
    public Screen createScreen() {
        return new Screen2();
    }

    @Override
    public Battery createBattery() {
        return new Battery2();
    }

    @Override
    public Memory createMemory() {
        return new Memory2();
    }

}

定义手机

package headfirst.hd.factory.abs;

public class IPhone {

    IPhoneXFactory factory;

    public IPhone(IPhoneXFactory factory) {
        this.factory = factory;
    }

    //手机的一些操作
    public void doOperate() {
        //屏幕

        //内存

        //电池
    }

}

测试

package headfirst.hd.factory.abs;

public class Client {

    public static void main(String[] args) {
        //整一个plus版本
        IPhoneXFactory factory = new PlusFactory();
        IPhone iPhone = new IPhone(factory);
        iPhone.doOperate();
    }

}

缺点,如果现在新增处理器产品,则必须修改抽象工厂接口,如下
产品

package headfirst.hd.factory.abs;

public interface Cpu {
    //这里简化,不做任何操作
}

抽象接口

package headfirst.hd.factory.abs;

public interface IPhoneXFactory {
    Screen createScreen();
    Battery createBattery();
    Memory createMemory();

    Cpu createCpu();
}

影响已有代码

总结

整理优点缺点
简单工厂用来生产同一等级结构中的任意产品,且设计简单对于增加新的产品,必须修改原有代码
工厂方法模式用来生产同一等级结构中任意产品,是对简单工厂的增强将影响降到最低
抽象工厂模式用来生产不同产品族的产品如何新增产品,必须修改抽象工厂接口

可根据实际需求,选择对应的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值