110.【十万字带你深入学习23种设计模式】(十一)

简介: 110.【十万字带你深入学习23种设计模式】

具体咖啡

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 12:51
 * @PackageName:com.jsxs.pattern.factory.before
 * @ClassName: LatteCoffe
 * @Description: TODO  拿铁咖啡
 * @Version 1.0
 */
public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}
package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 12:50
 * @PackageName:com.jsxs.pattern.factory.before
 * @ClassName: AmericanCoffee
 * @Description: TODO  美式咖啡
 * @Version 1.0
 */
public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}

具体甜品

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:21
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: Trmisu
 * @Description: TODO  提拉米苏类
 * @Version 1.0
 */
public class Tiramisu extends Dessert{
    @Override
    public void show() {
        System.out.println("提拉米苏-意大利风格");
    }
}
package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:23
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: MatchaMousee
 * @Description: TODO  抹茶慕斯类
 * @Version 1.0
 */
public class MatchaMousee extends Dessert{
    @Override
    public void show() {
        System.out.println("抹茶慕斯-美式风格");
    }
}

抽象大工厂

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:24
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: DessertFactory
 * @Description: TODO
 * @Version 1.0
 */
public interface DessertFactory {
    // 1.生产咖啡
    Coffee createCoffee();
    // 2.生产甜品
    Dessert createDessert();
}

美式套餐

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:25
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: AmericanFactoryImp
 * @Description: TODO  美式风格工厂
 * @Version 1.0
 */
public class AmericanFactoryImp implements DessertFactory{
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();  // 美式咖啡
    }
    @Override
    public Dessert createDessert() {
        return new MatchaMousee();  //抹茶慕斯
    }
}

意大利套餐

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:27
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: LatteFactoryImp
 * @Description: TODO
 * @Version 1.0
 */
public class LatteFactoryImp implements DessertFactory{
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
    @Override
    public Dessert createDessert() {
        return new Tiramisu();   //提拉米苏
    }
}

咖啡店

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:28
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: CofeStore
 * @Description: TODO
 * @Version 1.0
 */
public class CoffeeStore {
    private DessertFactory dessertFactory;
    public void setDessertFactory(DessertFactory dessertFactory) {
        this.dessertFactory = dessertFactory;
    }
    public void Order(){
        Coffee coffee = dessertFactory.createCoffee();
        Dessert dessert = dessertFactory.createDessert();
        System.out.println(coffee.getName());
        coffee.addMilk();
        coffee.addSuger();
        dessert.show();
    }
}

客户

package com.jsxs.pattern.factory.abstract_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 16:28
 * @PackageName:com.jsxs.pattern.factory.abstract_factory
 * @ClassName: CofeStore
 * @Description: TODO
 * @Version 1.0
 */
public class CoffeeStore {
    private DessertFactory dessertFactory;
    public void setDessertFactory(DessertFactory dessertFactory) {
        this.dessertFactory = dessertFactory;
    }
    public void Order(){
        Coffee coffee = dessertFactory.createCoffee();
        Dessert dessert = dessertFactory.createDessert();
        System.out.println(coffee.getName());
        coffee.addMilk();
        coffee.addSuger();
        dessert.show();
    }
}

如果我们需要再添加套餐(产品族)的话,只需要再加一个对应的工厂类即可,不需要再修改其他的类。

(4).优缺点

优点:

当一个产品族(套餐)中的多个对象被设计成一起工作的时候,它能保证客户端始终只使用同一个产品族中的对象 (套餐的对象必定一定)。

缺点:

当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。eg:美式套餐中我们赠送一个意大利风格的甜品。(不能赠送或新增单个产品,可以新增一整个套餐)

(5).使用场景
  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视、洗衣机、空调等。
  • 系统中有多个产品族。但每次只使用其中的某一族产品。如有人只喜欢穿一个指定的套餐(固定的产品族)
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实列的创建细节和内部结构。如: 输入法换皮肤,一整套一整套的换。生成不同的操作系统程序。
(6).JDK源码解析- Collection.iterator方法

使用迭代器遍历集合,获取集合中的元素。而单列集合获取迭代器的方法就使用到了工厂方法模式。

5.工厂模式的扩展💔 -(这个不属于23种)

简单工厂+配置文件解除耦合

可以通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂中加载配置文件中的全类名,并创建对象和存储,客户端如果需要对象对象,直接进行获取即可。

beans.properties: 配置文件

american=com.jsxs.pattern.factory.config_factory.AmericanCoffee
latte=com.jsxs.pattern.factory.config_factory.LatteCoffee

咖啡抽象类

package com.jsxs.pattern.factory.config_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 13:54
 * @PackageName:com.jsxs.pattern.factory.Single_Factory
 * @ClassName: Coffee
 * @Description: TODO
 * @Version 1.0
 */
public abstract class Coffee {
    // 0. 子类必须要实现抽象方法
    public abstract String getName();
    // 1.加糖
    public void addSuger() {
        System.out.println("加糖");
    }
    // 2.加奶
    public void addMilk() {
        System.out.println("加奶");
    }
}

具体实现

package com.jsxs.pattern.factory.config_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 12:50
 * @PackageName:com.jsxs.pattern.factory.before
 * @ClassName: AmericanCoffee
 * @Description: TODO  美式咖啡
 * @Version 1.0
 */
public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}
package com.jsxs.pattern.factory.config_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 12:51
 * @PackageName:com.jsxs.pattern.factory.before
 * @ClassName: LatteCoffe
 * @Description: TODO  拿铁咖啡
 * @Version 1.0
 */
public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

咖啡工厂类

package com.jsxs.pattern.factory.config_factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import java.util.Set;
/**
 * @Author Jsxs
 * @Date 2023/4/17 17:50
 * @PackageName:com.jsxs.pattern.factory.config_factory
 * @ClassName: CoffeeFactory
 * @Description: TODO  咖啡工厂类
 * @Version 1.0
 */
public class CoffeeFactory {
    // 1. 加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储
    //2.定义容器对象存储咖啡对象
    private static HashMap<String,Coffee> map=new HashMap<String,Coffee>();
    //3.加载配置文件,只需要加载一次
    static {
        //3.1创建Properties对象
        Properties properties = new Properties();
        //3.2调用load方法进行加载
        InputStream in = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties"); //获取输入流、读取哪个文件
        try {
            properties.load(in);  //这个参数是: 输入流。加载完毕之后,这个properties就已经存在数据了。
            //3.3从properties集合中获取全类名创建对象
            Set<Object> keys = properties.keySet();  // 获取配置文件中全部的键
            for (Object key : keys) {
                String ClassName = properties.getProperty((String) key); // 通过获取到配置文件中的键,我们得到值。
                //3.4 通过反射去创建对象
                Class aClass = Class.forName(ClassName);  // 通过加载类全民获取字节码对象
                Coffee coffee = (Coffee) aClass.newInstance(); //通过无参构造创建对象
                // 将名称和对象那个存储到我们自定义的容器中
                map.put((String) key,coffee);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    // 根据名称获取对象
    public static Coffee createCoffee(String type){
        return map.get(type);
    }
}
package com.jsxs.pattern.factory.config_factory;
/**
 * @Author Jsxs
 * @Date 2023/4/17 18:09
 * @PackageName:com.jsxs.pattern.factory.config_factory
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        Coffee coffee = CoffeeFactory.createCoffee("latte");
        System.out.println(coffee.getName());
    }
}

静态成员变量用来存储创建的对象(键存储的是名称、值存储的是对应的对象),而读取配置文件以及创建对象写在静态代码块中,目的就是只需执行一次

相关文章
|
3月前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
84 0
|
2月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
23 2
|
2月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
18 2
|
2月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
19 0
|
2月前
|
设计模式 数据可视化 程序员
设计模式学习心得之前置知识 UML图看法与六大原则(上)
设计模式学习心得之前置知识 UML图看法与六大原则(上)
18 0
|
3月前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
3月前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
3月前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
3月前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
3月前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式