文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java超详细讲解设计模式之一的工厂模式

2024-04-02 19:55

关注

工厂模式

在Java应用程序中对象无处不在,这些对象都需要进行创建,如果创建的时候直接new对象,那么如果我们要更换对象,所有new对象的地方都需要进行更改。违背了软件设计原则中的开闭原则。如果我们使用工厂生产对象,只需要在工厂中关注对象的改变即可,达到了与对象解耦的目的,工厂模式最大的特点就是解耦合

补充:

开闭原则: 对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。是为了使程序的扩展性好,易于维护和升级。

1.简单工厂

1.1结构

1.2实现

以点咖啡为例:

咖啡抽象类


public abstract class Coffee {
    
    public abstract  String getName();

    
    public  void addSugar(){
        System.out.println("加糖");
    }
    
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类


public class AmericanCoffee  extends Coffee{

@Override
    public String getName(){
        return "美式咖啡";
    }
}

拿铁咖啡类


public class LatteCoffee extends Coffee {

    @Override
    public String getName(){
        return "拿铁咖啡";
    }
}

咖啡工厂类


public class CoffeeFactory {

    public Coffee createCoffee(String type){
      Coffee coffee = null;
      if("american".equals(type)){
          coffee = new AmericanCoffee();
      }else if("latten".equals(type)){
          coffee = new LatteCoffee();
      }else{
          throw new RuntimeException("没有此类型的咖啡");
      }
      return coffee;
    }
}

咖啡店类


public class CoffeeStore {

    public Coffee orderCoffee(String type){
        CoffeeFactory factory = new CoffeeFactory();

      //调用生产咖啡的方法
        Coffee coffee = factory.createCoffee(type);
        coffee.addMilk();
        coffee.addSugar();

        return  coffee;
    }
}

测试类


public class Test {
    public static void main(String[] args) {
        CoffeeStore coffeeStore = new CoffeeStore();
        Coffee coffee = coffeeStore.orderCoffee("latten");
        System.out.println(coffee.getName());
    }
}

类图

image-20220324100400375

咖啡工厂负责生产咖啡(具体工厂),咖啡店通过咖啡工厂选取咖啡

其实简单工厂是大家在实际写代码的时候经常用到的,虽然简单工厂实现了咖啡店与咖啡的耦合,但是可以明显看到咖啡与咖啡工厂又耦合起来了,后期如果增加咖啡的新品种,我们需要修改咖啡工厂的代码,这又违背了“开闭原则”。

注意:

简单工厂和不使用工厂是有很大区别的,如果咖啡店有多个,不使用工厂如果遇到新增咖啡需要修改所有咖啡店,但是使用工厂只需要修改咖啡工厂,类似于将所有咖啡店抽取出一个抽象的咖啡店。

1.3优缺点

优点:

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

缺点:

增加新产品时还需要修改工厂类的代码,违背了“开闭原则”。

1.4扩展

静态工厂,将工厂类中创建对象的功能定义为静态的,这样不需要再创建工厂类,直接通过类名调用静态方法,类似于工具类


public class CoffeeFactory {
  //静态方法
    public static Coffee createCoffee(String type){
      Coffee coffee = null;
      if("american".equals(type)){
          coffee = new AmericanCoffee();
      }else if("latten".equals(type)){
          coffee = new LatteCoffee();
      }else{
          throw new RuntimeException("没有此类型的咖啡");
      }
      return coffee;
    }
}

2.工厂方法

对工厂进行抽象,每一种产品对应一个具体工厂,新增产品只需要再新增对应的具体工厂,符合”开闭原则“

2.1结构

2.2实现

抽象咖啡类和具体咖啡类不变

咖啡工厂(抽象工厂)


public interface CoffeeFactory {
    
    Coffee createCoffee();
}

美式咖啡工厂(具体工厂)


public class AmericanCoffeeFactory implements CoffeeFactory{
    //美式咖啡工厂对象,专门生产美式咖啡
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
}

拿铁咖啡工厂(具体工厂)


public class LatteCoffeeFactory implements CoffeeFactory{
    //拿铁咖啡工厂对象,专门生产拿铁咖啡
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

咖啡店


public class CoffeeStore {

    private CoffeeFactory factory;

    public void setFactory(CoffeeFactory factory) {
        this.factory = factory;
    }

    
    public Coffee orderCoffee() {
        Coffee coffee = factory.createCoffee();
        coffee.addSugar();
        coffee.addMilk();
        return coffee;
    }
}

测试类


public class Test {
    public static void main(String[] args) {
        //创建咖啡店对象
        CoffeeStore coffeeStore = new CoffeeStore();
        //创建工厂对象
        CoffeeFactory factory = new AmericanCoffeeFactory();
        coffeeStore.setFactory(factory);

        //点咖啡
        Coffee coffee = coffeeStore.orderCoffee();

        System.out.println(coffee.getName());
    }
}

类图

image-20220324105512679

我们只需要知道所点咖啡具体对应的工厂对象,通过咖啡店调用对应的工厂,由工厂创建咖啡对象实现点咖啡的过程

2.3优缺点

优点:

缺点:

每增加一个产品就要增加一个对应的具体工厂类,增加的系统的复杂性。如果具体产品种类过多,那么大量的工厂类不仅难以管理,而且也会造成程序中创建的对象过多,严重影响内存性能

3.抽象工厂

3.1结构

3.2实现

咖啡抽象类


public abstract class Coffee {
    
    public abstract  String getName();

    
    public  void addSugar(){
        System.out.println("加糖");
    }
    
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类


public class AmericanCoffee  extends Coffee{

@Override
    public String getName(){
        return "美式咖啡";
    }
}

拿铁咖啡类


public class LatteCoffee extends Coffee {

    @Override
    public String getName(){
        return "拿铁咖啡";
    }
}

甜品抽象类


public abstract class Dessert {
 //甜品抽象类

    public abstract void show();
}

抹茶慕斯类


public class MatchaMousse extends Dessert{

//抹茶慕斯类
    @Override
    public void show() {
        System.out.println("抹茶慕斯");
    }


}

提拉米苏类


public class Tiramisu  extends Dessert{
 //提拉米苏类
    @Override
    public void show() {
        System.out.println("提拉米苏");
    }
}

甜品工厂


public  interface DessertFactory {

    
    Coffee createCoffee();

    
    Dessert createDessert();

}

美式风味甜品工厂类


public class AmericanDessertFactory  implements DessertFactory{
    
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new MatchaMousse();
    }
}

意大利风味甜品工厂类


public class ItalyDessertFactory implements DessertFactory {

    
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

测试类


public class Test {
    public static void main(String[] args) {
        //ItalyDessertFactory factory = new ItalyDessertFactory();
           AmericanDessertFactory factory = new AmericanDessertFactory();
 
          Coffee coffee = factory.createCoffee()
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());

        dessert.show();

    }
}

类图

image-20220324150744271

由类图可见,抽象工厂不再是一个具体工厂对应一个产品,而是一个具体工厂对应一个产品族。如果需要增加一个产品族只需加对应的工厂类,符合”开闭原则“

3.3优缺点

优点:

在工厂方法的基础上减少了部分对象的创建,适合于每次只使用同一产品族的对象这类应用场景

缺点:

当产品族中需要增加一个产品时,所有工厂都要修改

4.模式扩展

配置文件+简单工厂

通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件的全类名,通过反射创建对象并存储在容器中,如果需要直接从容器中获取(Spring IOC原理)

4.1实现

1.定义配置文件


american = com.xue.config_factory.AmericanCoffee
latten = com.xue.config_factory.LatteCoffee

2.改进工厂类


public class CoffeeFactory {

    

    //1.定义容器对象存储咖啡对象
    private static HashMap<String, Coffee> map = new HashMap<>();


    //2.加载配置文件
    static {
        //创建 Properties对象
        Properties properties = new Properties();
        //调用properties对象中的load方法进行配置文件的加载
        InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
        try {
            properties.load(is);
            //从properties中获取全类名
            Set<Object> keys = properties.keySet();

            for (Object key : keys) {
                String className = properties.getProperty((String) key);
                //通过反射创建对象
                Class class1 = Class.forName(className);
                Coffee coffee = (Coffee) class1.newInstance();

                //将名称和对象存储在容器中
                map.put((String) key,coffee);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //根据名称获取对象
    public static Coffee createCoffee(String name) {


        return map.get(name);
    }
}

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

测试类


public class Test {
    public static void main(String[] args) {
        Coffee coffee = CoffeeFactory.createCoffee("american");
        System.out.println(coffee.getName());

        System.out.println("------------");

        Coffee latten = CoffeeFactory.createCoffee("latten");
        System.out.println(latten.getName());

    }

}

成功!!!

image-20220324165336860

以上就是Java设计模式——工厂模式的介绍及四种实现方式 往期链接:单例模式

到此这篇关于Java超详细讲解设计模式之一的工厂模式的文章就介绍到这了,更多相关Java 工厂模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯