一、工厂模式
工厂模式是一种非常常用的创建型设计模式,其提供了创建对象的最佳方式。在创建对象时,不会对客户端暴露对象的创建逻辑,而是通过使用共同的接口来创建对象。
工厂模式将对象的创建动作统一了起来,避免了代码的重复,也方便后续对对象创建方式的变动。
二、工厂模式的分类
简单工厂模式
- 定义
简单工厂模式:又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
image.png
- 实现方式
- 静态工厂模式,以计算器的实现为例:
首先定义计算器抽象类:
/**
* 有两个属性存放计算值和一个返回结果的方法
**/
public abstract class Calculate {
protected double numberA;
protected double numberB;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public abstract double getResult();
}
定义具体实现类,加减乘除:
public class OperationAdd extends Calculate {
@Override
public double getResult() {
return numberA+numberB;
}
}
public class OperationSub extends Calculate {
@Override
public double getResult() {
return numberA-numberB;
}
}
public class OperationMul extends Calculate {
@Override
public double getResult() {
return numberA*numberB;
}
}
public class OperationDiv extends Calculate {
@Override
public double getResult() {
return numberA/numberB;
}
}
创建简单工厂类:
public class OperationFactory {
public static Calculate createOperation(String operation) {
Calculate cal=null;
switch(operation) {
case "add":{
cal=new OperationAdd();
break;
}
case "sub":{
cal=new OperationSub();
break;
}
case "mul":{
cal=new OperationMul();
break;
}
case "div":{
cal=new OperationDiv();
break;
}
}
return cal;
}
}
测试类:
public class Main {
public static void main(String[] args) {
Calculate cal;
cal=OperationFactory.createOperation("add");
cal.setNumberA(6);
cal.setNumberB(12);
System.out.println(cal.getResult());
}
}
以上是以静态工厂模式实现计算机类创建的代码实现。从代码的实现中可以很明显的看出,如果要增加一个实例对象的话则需要修改工厂类的代码增加一个case
分支,这样当然是违反了开闭原则的,所以这种方式是不太友好的。
- 反射方式实现
package com.qcjy.factory;
//动物接口
interface Animal1{
public void speak();
}
//人实现类
class Man1 implements Animal{
@Override
public void speak() {
System.out.println("我是人我会说话:哈哈哈!!!");
}
}
//狗实现类
class Dog1 implements Animal{
@Override
public void speak() {
System.out.println("我是小狗不会说话:汪汪汪!!!");
}
}
//工厂类
class Factory1{
public Object getAnimal(String className) throws Exception{
Class<?> cls = Class.forName(className);
Object obj = cls.newInstance();
return obj;
}
}
//测试类
public class ReflectFactory {
public static void main(String[] args) throws Exception{
Factory1 factory = new Factory1();
Animal an = (Animal)factory.getAnimal("com.qcjy.factory.Man1");
an.speak();
}
}
以上是简单工厂模式以反射方式的实。反射的实现方式还是很简单的,但是又两个比较大的隐患:
- 反射的实现比较影响性能,在对性能要求很高的场景下要避免使用
- 因为我们反射创建的对象属性是被SoftReference软引用的,所以当-XX:SoftRefLRUPolicyMSPerMB 没有设置好的话会一直让机器CPU很高
总结下来,当代码比较简单,预计后续修改难度不高且改动不频繁的情况下可以使用,但需要考虑其所带来的缺点:违反开闭原则,反射影响性能等等
工厂方法模式
- 定义
简单工厂模式违背了开闭原则,而工厂方法模式则是简单工厂模式的进一步深化,其不像简单工厂模式通过一个工厂来完成所有对象的创建,而是通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建。
当对象的创建过程比较复杂,需要组合其他类对象做各种初始化操作时,推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中使得每个工厂类不过于复杂。而使用简单工厂模式则会将所有的创建逻辑都放到一个工厂类,会导致工厂类过于复杂,
- 实现
工厂抽象类:
package factory.factoryMethod;
import factory.model.Computer;
public abstract class ComputerFactory {
protected abstract Computer create();
}
具体工厂实现,不同的工厂负责创建相应的具体对象:
package factory.factoryMethod;
import factory.model.Computer;
import factory.model.HuaweiComputer;
public class HuaweiComputerFactory extends ComputerFactory {
protected Computer create() {
return new HuaweiComputer();
}
}
package factory.factoryMethod;
import factory.model.Computer ;
import factory.model.XiaomiComputer;
public class XiaomiComputerFactory extends ComputerFactory {
protected Computer create() {
return new XiaomiComputer();
}
}
Client客户端:
package factory.factoryMethod;
import factory.model.Computer ;
public class Client {
public static void main(String[] args) {
Computer computer = new HuaweiComputerFactory().create();
computer.powerOn();
computer.powerOff();
Computer computer1 = new XiaomiComputerFactory().create();
computer1.powerOn();
computer1.powerOff();
}
}
// 结果
Huawei Computer power on
Huawei Computer power off
Xiaomi Computer power on
Xiaomi Computer power off
抽象工厂模式
- 定义
抽象工厂模式:提供一个创建一系列相关或互相依赖的接口,而无需指定具体它们具体的类
在工厂方法模式中,工厂仅可创建一种对象;然而,在抽象工厂模式中,工厂不只是可创建一种对象,而是可以创建一组对象。
- 实现
首先定义具体产品类:
package factory.abstractFactory.model;
/**
* 电脑:开机,关机
*/
public interface Computer {
void powerOn();
void powerOff();
}
台式电脑:
package factory.abstractFactory.model;
public abstract class DesktopComputer implements Computer {
public abstract void powerOn();
public abstract void powerOff();
}
package factory.abstractFactory.model;
public class HuaweiDesktopComputer extends DesktopComputer {
@Override
public void powerOn() {
System.err.println("HuaweiDesktopComputer power on");
}
@Override
public void powerOff() {
System.err.println("HuaweiDesktopComputer power off");
}
}
package factory.abstractFactory.model;
public class XiaomiDesktopComputer extends DesktopComputer {
@Override
public void powerOn() {
System.err.println("XiaomiDesktopComputer power on");
}
@Override
public void powerOff() {
System.err.println("XiaomiDesktopComputer power off");
}
}
笔记本电脑:
package factory.abstractFactory.model;
public abstract class NoteBookComputer implements Computer {
public abstract void powerOn();
public abstract void powerOff();
}
package factory.abstractFactory.model;
public class HuaweiNoteBookComputer extends NoteBookComputer {
@Override
public void powerOn() {
System.err.println("HuaweiNoteBookComputer power on");
}
@Override
public void powerOff() {
System.err.println("HuaweiNoteBookComputer power off");
}
}
package factory.abstractFactory.model;
public class XiaomiNoteBookComputer extends NoteBookComputer {
@Override
public void powerOn() {
System.err.println("XiaomiNoteBookComputer power on");
}
@Override
public void powerOff() {
System.err.println("XiaomiNoteBookComputer power off");
}
}
抽象工厂类,定义了生产台式电脑和笔记本电脑的抽象方法,由不同品牌的具体工厂类实现:
package factory.abstractFactory;
import factory.abstractFactory.model.Computer;
public abstract class AbstractComputerFactory {
public abstract Computer createDesktopComputer();
public abstract Computer createNoteBookComputer();
}
华为工厂类:
package factory.abstractFactory;
import factory.abstractFactory.model.Computer;
import factory.abstractFactory.model.HuaweiDesktopComputer;
import factory.abstractFactory.model.HuaweiNoteBookComputer;
public class HuaweiComputerFactory extends AbstractComputerFactory {
public Computer createDesktopComputer() {
return new HuaweiDesktopComputer();
}
public Computer createNoteBookComputer() {
return new HuaweiNoteBookComputer();
}
}
Xiaomi工厂类:
package factory.abstractFactory;
import factory.abstractFactory.model.Computer;
import factory.abstractFactory.model.XiaomiDesktopComputer;
import factory.abstractFactory.model.XiaomiNoteBookComputer;
public class XiaomiComputerFactory extends AbstractComputerFactory {
public Computer createDesktopComputer() {
return new XiaomiDesktopComputer();
}
public Computer createNoteBookComputer() {
return new XiaomiNoteBookComputer();
}
}
Client客户端:
package factory.abstractFactory;
import factory.abstractFactory.model.Computer;
public class Client {
public static void main(String[] args) {
HuaweiComputerFactory huaweiComputerFactory = new HuaweiComputerFactory();
Computer desktopComputer = huaweiComputerFactory.createDesktopComputer();
desktopComputer.powerOn();
desktopComputer.powerOff();
Computer noteBookComputer = huaweiComputerFactory.createNoteBookComputer();
noteBookComputer.powerOn();
noteBookComputer.powerOff();
XiaomiComputerFactory XiaomiComputerFactory = new XiaomiComputerFactory();
Computer desktopComputer1 = XiaomiComputerFactory.createDesktopComputer();
desktopComputer1.powerOn();
desktopComputer1.powerOff();
Computer noteBookComputer1 = XiaomiComputerFactory.createNoteBookComputer();
noteBookComputer1.powerOn();
noteBookComputer1.powerOff();
}
}
// 结果
HuaweiDesktopComputer power on
HuaweiDesktopComputer power off
HuaweiNoteBookComputer power on
HuaweiNoteBookComputer power off
XiaomiDesktopComputer power on
XiaomiDesktopComputer power off
XiaomiNoteBookComputer power on
XiaomiNoteBookComputer power off
总结下来就是:
工厂模式可以理解为是对对象的单一维度的分类,比如手机可以分为小米或华为,一个分类就是一个工厂比如,小米手机工厂,华为手机工厂。
抽象工厂模式可以理解为二维分类,比如电脑按可以按形状分类为台式机和笔记本,按品牌分又可以分为华为电脑,小米电脑。这时根据业务性质不同可按照不同的形式进行抽象。
假如按形状区分台式电脑工厂和笔记本电脑工厂他们都继承自抽象工厂,抽象工厂定义了华为电脑和小米电脑的接口,这意味着每个工厂都可以生产不同品牌的产品,比如台式电脑工厂可以生产小米台式电脑和华为台式电脑,而笔记本电脑工厂可以生产小米笔记本电脑和华为笔记本电脑。
假如按品牌区分华为电脑工厂和小米电脑工厂他们都继承自抽象工厂,抽象工厂定义了台式电脑和笔记本电脑的接口,这意味着每个工厂都可以生产不同形式的产品,比如华为电脑工厂可以生产华为台式电脑和华为笔记本电脑,而小米电脑工长可以生产小米笔记本电脑和小米台式电脑。
网友评论