Java设计模式-工厂模式(1)简单工厂模式

简介: Java设计模式-工厂模式(1)简单工厂模式

微信截图_20220524180242.png



今天就让我们接着学习Java设计模式中的工厂模式吧,持续更新中。

让我们一起学习设计模式吧,说它是基础也是基础,说它不是,又确实不是。它穿插在各处。学好它也是为了能让自己更进一步吧。

很喜欢一句话:“八小时谋生活,八小时外谋发展”。共勉

封面地点:湖南省永州市蓝山县舜河村

作者:用心笑*😁

设计模式系列


一、前言


我们先别急着想工厂模式是什么样的啊

先看看下面这个例子啊,怎么设计,如何写,才能更好。

一步一步引出Java工厂模式。


1)例子


需求:设计一个咖啡店点餐系统。


设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。


代码是比较简单的,我这是采取一步一步引入的,如果不喜欢,可以直接看下文。

我们先用曾经的方式来设计和进行代码的编写。


2)类图关系


微信截图_20220524180432.png


3)代码实现


我们先用以前的方式来实现一遍哈。


1、先写好Coffee这个抽象类


public abstract class Coffee {
    public abstract void addMilk();
    public abstract void addSugar();
    public abstract String getName();
}


2、再写好美式咖啡和拿铁咖啡继承Coffee抽象类


public class AmericanCoffee extends Coffee {
    @Override
    public void addMilk() { System.out.println("给咖啡加奶"); }
    @Override
    public void addSugar() { System.out.println("给咖啡加糖"); }
    @Override
    public String getName() { return "美式咖啡"; }
}


public class LatteCoffee extends Coffee {
    @Override
    public void addMilk() { System.out.println("给咖啡加奶"); }
    @Override
    public void addSugar() {  System.out.println("给咖啡加糖"); }
    @Override
    public String getName() { return "拿铁咖啡"; }
}


3、咖啡店


public class CoffeeStore {
    public Coffee createCoffee(String type){
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        coffee.addMilk();
        coffee.addSugar();
        return coffee;
    }
}


4、写个客户端来测试点咖啡哈


public class Client {
    public static void main(String[] args) {
        CoffeeStore coffeeStore = new CoffeeStore();
        Coffee coffee = coffeeStore.createCoffee("americano");
        System.out.println(coffee.getName());
        /**
         * 输出:
         * 给咖啡加奶
         * 给咖啡加糖
         * 美式咖啡
         */
    }
}


其实乍一看没啥问题,但是如果我这个需要增加几种咖啡,你说该如何才合适勒?

是不是需要修改CoffeeStore的代码。又如果要开设美团外卖点单呢?又如何改呢?

在java中,万物皆对象。


如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。(而且这种重复工作简直想死


如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦


接下来就出现了简单工厂模式(简单工厂模式并非23种经典模式之内,更像是一种编程习惯吧)。😁


二、简单工厂模式


2.1、概述:


简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。


简单工厂包含如下角色:


  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。 (例子中的咖啡)


  • 具体产品 :实现或者继承抽象产品的子类  (例子中的美式咖啡、拿铁咖啡等)


  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。 (一个来创建对象的工厂)


使用场景


工厂类负责创建的对象比较少;


客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;


2.2、类图关系:


微信截图_20220524180724.png


简单来说就是在原有的设计上加了一层(没有什么是加一层解决不了的,不行就加两层(狗头保命))😁


2.3、代码修改:


在原有基础上做了一些修改:


增加一个SimpleCoffeeFactory类,在这个地方进行对象的创建。😀


public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffee;
    }
}


再修改一下CoffeeStore类


public class CoffeeStore {
    public Coffee createCoffee(String type){
        SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
        Coffee coffee = factory.createCoffee(type);
        coffee.addMilk();
        coffee.addSugar();
        return coffee;
    }
}


看起来好像只是把创建对象的权力给到了SimpleCoffeeFactory,没有什么其他操作,但是就是这个SimpleCoffeeFactory工厂类,已经将CoffeeStore类和Coffee对象解耦了,CoffeeStore不再需要管具体产品对象是如何创建的,只需要负责自己的事情就可以了,明确了各自的职责和权利,有利于整个软件体系结构的优化


当然另一方面又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。


后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。


工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。


2.4、优缺点


优点:


1)封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。


2)工厂类根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。


缺点:当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利,违背了“开闭原则”


2.5、扩展-简单静态工厂


在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的,这个就是静态工厂模式,它也不是23种设计模式中的。代码如下


public class SimpleCoffeeFactory {
    public static Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}


2.6、扩展-简单工厂+配置文件解除耦合


可以通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。


在工厂类中加载配置文件中的全类名,并创建对象进行存储,客户端如果需要对象,直接进行获取即可。


  1. 定义一个配置文件 my.properties


american=com.crush.factory.simple_factory_properties.AmericanCoffee
latte=com.crush.factory.simple_factory_properties.LatteCoffee


  1. 改进工厂类


public class CoffeeFactory {
    private static Map<String,Coffee> map = new HashMap();
    static {
        Properties p = new Properties();
        InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("my.properties");
        try {
            p.load(is);
            //遍历Properties集合对象
            Set<Object> keys = p.keySet();
            for (Object key : keys) {
                //根据键获取值(全类名)
                String className = p.getProperty((String) key);
                //获取字节码对象
                Class clazz = Class.forName(className);
                Coffee obj = (Coffee) clazz.newInstance();
                map.put((String)key,obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Coffee createCoffee(String name) {
        return map.get(name);
    }
}


  1. 静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件以及创建对象写在静态代码块中,目的就是只需要执行一次。
    这种方式用的也很多,常见也很简单。


三、结语


这个简单工厂并不完善,增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”,所以才有了后文的工厂模式、抽象工厂模式


持续更新中哦。


目录
相关文章
|
22天前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
36 0
[Java]23种设计模式
|
6天前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
1月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
1月前
|
设计模式 Java
Java设计模式
Java设计模式
28 0
|
1月前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
29 0
|
5月前
|
设计模式 缓存 安全
Java设计模式的单例模式应用场景
Java设计模式的单例模式应用场景
57 4
|
2月前
|
设计模式 安全 Java
Java 编程中的设计模式:单例模式的深度解析
【9月更文挑战第22天】在Java的世界里,单例模式就像是一位老练的舞者,轻盈地穿梭在对象创建的舞台上。它确保了一个类仅有一个实例,并提供全局访问点。这不仅仅是代码优雅的体现,更是资源管理的高手。我们将一起探索单例模式的奥秘,从基础实现到高级应用,再到它与现代Java版本的舞蹈,让我们揭开单例模式的面纱,一探究竟。
40 11
|
3月前
|
设计模式 存储 负载均衡
【五】设计模式~~~创建型模式~~~单例模式(Java)
文章详细介绍了单例模式(Singleton Pattern),这是一种确保一个类只有一个实例,并提供全局访问点的设计模式。文中通过Windows任务管理器的例子阐述了单例模式的动机,解释了如何通过私有构造函数、静态私有成员变量和公有静态方法实现单例模式。接着,通过负载均衡器的案例展示了单例模式的应用,并讨论了单例模式的优点、缺点以及适用场景。最后,文章还探讨了饿汉式和懒汉式单例的实现方式及其比较。
【五】设计模式~~~创建型模式~~~单例模式(Java)
|
2月前
|
设计模式 Java 安全
Java设计模式-单例模式(2)
Java设计模式-单例模式(2)
|
6月前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式