ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式 02 工厂模式

2022-07-10 12:02:29  阅读:165  来源: 互联网

标签:02 水果 Apple 工厂 Orange new 设计模式 public


参考源

https://www.bilibili.com/video/BV1u3411P7Na?spm_id_from=333.999.0.0&vd_source=299f4bc123b19e7d6f66fefd8f124a03


工厂模式(Factory Pattern)属于创建型模式

它提供了一种创建对象的最佳方式。

在工厂模式中,创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

如果需要创建一个对象,最简单的方式就是直接 new 一个。

而工厂模式代替了传统的直接 new 的形式,那么为什么要替代呢?

如果所有的对象都通过 new 的方式去创建,那么当程序中大量使用此对象时,突然有一天这个对象的构造方法或是类名发生了修改,那就得逐个去进行修改。

根据迪米特法则,应该尽可能地少与其他类进行交互,所以可以将那些需要频繁出现的对象创建,封装到一个工厂类中。

当需要对象时,直接调用工厂类中的工厂方法来生成对象,这样,就算类出现了变动,只需要修改工厂中的代码即可,而不是大面积地进行修改。

同时,可能某些对象的创建并不只是一个 new 就可以搞定,可能还需要更多的步骤来准备构造方法需要的参数。

来看看如何使用工厂模式创建对象,既然是工厂,那么就来创建点工厂需要生产的东西:

// 水果抽象类
public abstract class Fruit {
    private final String name;
    
    public Fruit(String name){
        this.name = name;
    }

    // 打印当前水果名称,还有对象的 hashCode
    @Override
    public String toString() {
        return name + "@" + hashCode();
    }
}
// 苹果,继承自水果
public class Apple extends Fruit{   

    public Apple() {
        super("苹果");
    }
    
}
// 橘子,也是继承自水果
public class Orange extends Fruit{  
    
    public Orange() {
        super("橘子");
    }
    
}

通常情况下,直接 new 就可以得到对象了:

Apple apple = new Apple();
Orange orange = new Orange();

现在将对象的创建封装到工厂中:

// 水果工厂
public class FruitFactory {
    
    /**
     * 这里就直接来一个静态方法根据指定类型进行创建
     * @param type 水果类型
     * @return 对应的水果对象
     */
    public static Fruit getFruit(String type) {
        switch (type) {
            case "苹果":
                return new Apple();
           	case "橘子":
                return new Orange();
            default:
                return null;
        }
    }
    
}

现在就可以使用此工厂来创建对象了:

// 直接问工厂要,而不是自己去创建
Apple apple = FruitFactory.getFruit("苹果");
Orange orange = FruitFactory.getFruit("橘子");

不过这样还是有一些问题,前面提到了开闭原则,一个软件实体,比如类、模块和函数应该对扩展开放,对修改关闭。

此时如果需要新增一种水果,比如桃子,那么就得去修改工厂提供的工厂方法了,这样是不太符合开闭原则的。

因为工厂实际上是针对于调用方提供的,所以应该尽可能对修改关闭。

所以,我们就利用对扩展开放,对修改关闭的性质,将简单工厂模式改进为工厂方法模式,既然不让改,那么就看看如何去使用扩展的形式:

// 将水果工厂抽象为抽象类,添加泛型 T 由子类指定水果类型
public abstract class FruitFactory<T extends Fruit> {
    // 不同的水果工厂,通过此方法生产不同的水果
    public abstract T getFruit();  
}
// 苹果工厂,直接返回 Apple
public class AppleFactory extends FruitFactory<Apple> {  
    
    @Override
    public Apple getFruit() {
        return new Apple();
    }
    
}
// 橘子工厂,直接返回 Orange
public class OrangeFactory extends FruitFactory<Orange> {  
    
    @Override
    public Orange getFruit() {
        return new Orange();
    }
    
}

这样,就可以使用不同类型的工厂来生产不同类型的水果了,如果新增了水果类型,直接创建一个新的工厂类就行,不需要修改之前已经编写好的内容。

// 使用对应的工厂生产对应的对象
Apple apple = AppleFactory.getFruit();
Orange orange = OrangeFactory.getFruit();

这样,就简单实现了工厂方法模式,通过工厂来屏蔽对象的创建细节,使用者只需要关心如何去使用对象即可。

标签:02,水果,Apple,工厂,Orange,new,设计模式,public
来源: https://www.cnblogs.com/codesail/p/16462902.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有