工厂设计模式(1)—普通的工厂模式

工厂设计模式(1)—普通的工厂模式
工厂设计模式(2)—枚举实现工厂模式

序: 为什么需要工厂模式?

学习工厂模式之前,还是思考下这个问题吧,免得学到一身本领之后,却不知道在哪里使用。

小胖(思考模式):小悠同学,为什么需要工厂模式呀?

小悠(怼人模式):你似不似傻?你想买一个冰箱,需要关注冰箱如何造的吗?交给工厂帮你创建就行了。你需要的是冰箱。冰箱你知道吗?!

小胖(可怜无助又弱小模式):咋一听,很有道理的,但是...但是,我们在一个静态方法里面实现造冰箱的过程,也不一定非得要工厂模式呀

小悠(教导模式):好吧,我根据我理解的说一下吧。(此时,小胖偷偷的拿出本子)

  1. 还是我之前说的那点,用户创建对象的目的就是使用对象。将复杂的,重复的逻辑交给工厂。不仅减少了冗余代码,减少出错,关键是与业务代码解耦。这其实就是Spring IOC的原理之一。

  2. 一般来说,若只是创建一种对象的话,我们没必要使用工厂模式。但是若是创建多个功能相似的对象呢?根据他们的相似之处,将其整合到一个类中,其实就是工厂类。我们在设计工厂类的时候,还要注意“开放-封闭”原则。

小胖(舔狗模式):小悠好棒!那为什么工厂模式可以有简单工厂模式、工厂模式、抽象工厂模式?

小悠(填坑模式):这就是我说的两点,“开放-封闭原则”“相似之处”了。

相似之处:可以分为“产品等级”“产品族”工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。

  • 产品等级:苹果手机,华为手机,三星手机。都是手机,只是等级不同。
  • 产品族:ipone,ipad,Mac,都是苹果一族的商品。
  1. 简单工厂模式:核心是具体工厂类,但是扩展的时候,可能要修改工厂类,不符合“开放-封闭”原则。

  2. 工厂方法模式:增加了抽象工厂模式这一角色,那么扩展时,可以增加具体的子类工厂。【注意:对象纵向切分,即产品等级】通过具体工厂获取的是一类对象,比如说是手机对象。

  3. 抽象工厂模式:与工厂方法的不同的是:【对象的横向切分,即产品族】,关注的点是一个产品族。比如:具体工厂生产的是:电器总类——苹果品牌:ipone,iPad,Mac;

小胖(明悟模式):嗯,工厂模式这么多实现方式,这不是设计者在卖弄什么。比如工厂方法模式,虽然实现了“开放-封闭”原则,但是,当添加“小米品牌”一系列对象时,每一个具体工厂都需要进行修改。是不是也违反了开闭原则?具体选用什么工厂模式,要根据具体的场景来说。

工厂设计模式(1)—普通的工厂模式_第1张图片
产品等级和产品族

1. 简单工厂模式

创建类模式 静态工厂 共同父类

1.1 简单工厂模式的定义

简单工厂模式属于类的创建型模式,又叫静态工厂模式通常专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

1.2 简单工厂模式的角色

  • 工厂角色:

简单工厂模式的核心,它负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象。

  • 抽象角色

简单工厂模式:所创建的所有对象的父类,他负责描述所有实例的所共有的公共接口。

  • 具体产品角色

简单工厂模式:所创建的具体实例对象(共同接口:抽象角色)。

1.3 简单工厂模式的代码实现

此时,就应该推荐下我的反射三部曲了。

首先我先介绍下,虚拟机类加载过程,大体可以分为三个阶段加载、连接、初始化。JVM那点事-虚拟机类加载机制

  • 加载阶段,会将class文件读取到虚拟机中,并且在内存(一般是堆)生成Class对象。
  • 反射会导致初始化阶段的执行。

复习盘点-反射知多少-1(官网+完整代码实现)。在加载的时候,会生成Class对象,是反射的入口。
获取到Class对象的三种方法:

  • 对象可用的情况下:object.getClass();

  • 类型可用但是没有对象的情况下:Object.class();

  • 类的全限定名可用的情况下:Class.forName(String className);


简单工厂模式——抽象角色

//抽象角色
public interface Fruit {
    //获取水果
    public void get();
}

简单工厂模式——具体产品角色

//具体产品对象
public class Apple implements Fruit{
    @Override
    public void get() {
        System.out.println("采集苹果");
    }
}

//具体产品对象
public class Banana implements Fruit{
    @Override
    public void get() {
        System.out.println("采集香蕉");
    }
}

简单工厂模式——工厂角色

//静态工厂
public class FruitFactory {

    //静态工厂方法,获取各个对象实例
    public static Fruit getFruit(String type) throws IllegalAccessException, InstantiationException {
        if (type.equalsIgnoreCase("apple")) {
            //通过反射创建对象
            return Apple.class.newInstance();
        } else if (type.equalsIgnoreCase("banana")) {
            return Banana.class.newInstance();
        } else {
            throw new RuntimeException("type is illegal");
        }
    }

    //静态方法获取对象实例
    public static Fruit getFruitByClassName(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class name = Class.forName(className);
        return (Fruit) name.newInstance();
    }
}

简单工厂模式——测试方法

public class TestSimpleFactory {

    public static void main(String[] args) {
        try {
            Apple apple = (Apple) FruitFactory.getFruit("apple");
            Banana banana = (Banana) FruitFactory.getFruit("banana");
            apple.get();
            banana.get();
            //方法二获取实例对象
            Apple apple1 = (Apple) FruitFactory.getFruitByClassName("com.simpleFactory.Apple");
            apple1.get();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

测试结果就不说了,一定是获取到对象了。注意,咱们在工厂角色中通过反射获取到了实例对象。并且,工厂类可以被外界直接调用,创建所需的产品对象。

1.4 简单工厂模式的优缺点

还是科普一波 类设计的原则 之一——“开放-封闭”原则。啥意思呢?对扩展开放,对修改关闭。

优点:
在这个模式中,工厂类是整个模式的关键所在,它包含了必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。

  • “便捷化”创建对象。用户可以直接通过工厂类创建所需的实例,而无需了解这些对象是如何创建和组织的,有利于整个软件结构的优化。

缺点:
我们在上面,工厂类的getFruit方法可以看出,简单工厂的缺点也体现在其工厂类上。

  • “高内聚”方面做得不是很好,工厂类集中了所有实例的创建模式。
  • “扩展性”不是很好,当系统中具体产品类不断增多的时候,可能会要求工厂类也要做相应的修改。

2. 工厂方法模式

创建型模式 多态工厂模式

不吹不黑的说哦,简单工厂模式扩展性不是很好,违反了开放-封闭原则。那我们如何实现对扩展开发,对修改封闭呢?
小胖:采用“接口”,定义一个工厂接口,将具体的工厂实现推迟到子类当中。工厂接口不进行修改,通过子类扩展工厂接口

正如上面所言:核心工厂类不再负责具体产品的创建,这样核心类成为一个抽象工厂角色。仅负责具体工厂子类必须实现的接口。
这样进一步抽象化的好处是:使得工厂方法模式可以在系统不修改具体工厂角色的情况下引入新的产品。

2.1 工厂模式的角色

  • 抽象工厂角色
    工厂方法模式的核心,任何工厂类都必须实现这个接口。

  • 具体工厂角色
    具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

  • 抽象产品角色
    工厂方法模式所创建的具体产品角色的父类,负责描述所有实例所共有的公共接口。

  • 具体产品角色
    工厂方法模式所创建的具体实例对象。

2.2 工厂模式的代码实现

  • 抽象工厂角色
//抽象工厂角色,仅负责具体子类对象的实现接口
public interface FruitFactory {
    public Fruit getFruit();
}
  • 具体工厂角色
//创建具体工厂角色,继承于抽象工厂角色
public class AppleFactory implements FruitFactory{
    @Override
    public Fruit getFruit() {
        return new Apple();
    }
}

public class BananaFactory implements FruitFactory {
    @Override
    public Fruit getFruit() {
        return new Banana();
    }
}

抽象产品角色

//抽象角色
public interface Fruit {
    //获取水果
    public void get();
}

具体产品角色

//具体产品对象
public class Apple implements Fruit{
    @Override
    public void get() {
        System.out.println("采集苹果");
    }
}

//具体产品对象
public class Banana implements Fruit{
    @Override
    public void get() {
        System.out.println("采集香蕉");
    }
}

测试类代码

    public static void main(String[] args) {
        FruitFactory appleFactory = new AppleFactory();
        Apple apple = (Apple) appleFactory.getFruit();
        apple.get();
    }

2.3 工厂模式的和简单工厂模式的比较

  • 结构上的不同不是很明显,工厂方法类的核心是抽象工厂类,而简单工厂模式把核心放在了具体类上。
  • 系统扩展新的产品对象时,仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行修改,也不需要修改客户端,很好的符合了“开放-封闭”原则,而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。

3. 抽象工厂模式

只是划分的角度不同,工厂方法模式好似“纵切”,一类对象归到一个具体工厂;而抽象工厂模式好似“横切”,不同对象中相同属性归到一个具体工厂。

3.1 什么是抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象最一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端不必指定产品的具体类型情况下,能够创建多个产品族的产品对象。

【产品族:比如肯德基、麦当劳,都是一个个产品族,一个具体的工厂类,只创建这一个产品族的对象。】

3.2 抽象工厂模式中角色

  • 抽象工厂角色
    抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

  • 具体工厂角色
    具体工厂角色类是抽闲工厂的一个实现,负责实例化某个产品族中的产品对象。

  • 抽象角色
    抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

  • 具体产品对象
    抽象模式所创建的具体实例对象。

3.3 抽象工厂模式代码实现

抽象工厂角色

public interface FruitFactory {
    public Fruit getApple();

    public Fruit getBanana();
}

具体工厂角色

水果按南方和北方划分。

public class NorthFruitFactory implements FruitFactory{
    @Override
    public Fruit getApple() {
        return new NorthApple();
    }

    @Override
    public Fruit getBanana() {
        return new NorthBanana();
    }
}

抽象产品角色

//水果接口
public interface Fruit {
    //获取水果
    public void get();
}

//苹果种类的抽象方法
public abstract class Apple implements Fruit {
    public abstract void get();
}

public abstract class Banana implements Fruit {
    public abstract void get();
}

具体产品对象

public class NorthApple extends Apple {
    @Override
    public void get() {
        System.out.println("采集北方苹果");
    }
}

public class NorthBanana extends Banana{
    @Override
    public void get() {
        System.out.println("采集北方香蕉");
    }
}

测试方法

    public static void main(String[] args) {
        FruitFactory appleFactory = new NorthFruitFactory();
        NorthApple apple = (NorthApple) appleFactory.getApple();
        apple.get();
    }

你可能感兴趣的:(工厂设计模式(1)—普通的工厂模式)