设计模式之工厂模式详解

设计模式之工厂模式详解这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战 工厂模式 简单工厂模式 简单工厂模式不属于GOF23种设计模式里面的,属于创建型设计模式,是指由一个工厂对象决定创建出哪一种产

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

工厂模式

简单工厂模式

简单工厂模式不属于GOF23种设计模式里面的,属于创建型设计模式,是指由一个工厂对象决定创建出哪一种产品类的实例

将一个对象创建的过程包装起来,用户看不到创建的细节

原始代码

这里我通过一个例子来展示下简单工厂模式,先来一个没有使用简单工厂的例子,然后在写一个通过简单工厂优化的例子进行对比.

这个我有个课程的类,我要将他们创建出来,先来看下没有通过工厂模式的写法\

JavaCourse类

    public class JavaCourse {
        public void course(){
            System.out.println("这个是Java课程");
        }
    }

下面这个是main方法

 public class Test {
    public static void main(String[] args) {
        JavaCourse javaCourse = new JavaCourse();
        javaCourse.course();
    }
 }

这个时候我需要加一个新的课程PythonCourse,需要加这么一个新的类

当想到这里,我们有多个课程的时候,就应该想到这里我们应该针对接口编程了,因为他们都是课程,它们都有相同的方法,所以这个我可以抽象出来课程的接口类ICourse,然后让JavaCourse和PythonCourse来实现它\

改造代码

这里我除了重新把代码改造下再新加一个PythonCourse

新增了一个接口类

public interface ICourse {
    void course();
}

改造后的JavaCourse

public class JavaCourse implements ICourse{
    @Override
    public void course() {
        System.out.println("这个是Java课程");
    }    
}

新增的PythonCouse

public class PythonCourse implements ICourse{
    @Override
    public void course() {
        System.out.println("这个是Python课程");
    }
}

上面的这些准备完成后,这里还需要一个工厂类,因为我要通过这个工厂来完成这两个对象的创建\

public class CourseFactory {
    public ICourse createCourse(String courseName){
        if(courseName.equalsIgnoreCase("java")){
            return new JavaCourse();
        }else if(courseName.equalsIgnoreCase("python")){
            return new PythonCourse();
        }
        return null;
    }
}

测试类     

public class Test {
    public static void main(String[] args) {
        ICourse course = new CourseFactory().createCourse("python");
        if(course!=null){
            course.course();
        }
    }
}

pythonCourse

在高层类中,我只需要传入对应的参数,就可以得到相应的对象,现在完需关注创建对象的过程,只需关注结果就可以了

这里给大家说一个小技巧,有兴趣的可以看下.现在我所写的工厂类在传入参数的时候有时不注意可能会轮输入错误,这个IDE是不会报错了,这里我们可以修改下,通过反射的方式来将对象创建出来.\

public ICourse createCourse(Class<? extends ICourse> clazz){
    try {
        if(clazz != null){
            return clazz.newInstance();
        }
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

测试类

ICourse course = new CourseFactory().createCourse(JavaCourse.class);
course.course();

这里在传入参数的时候,只能传入ICourse的子类的时候才可以传入,不然的话会报错,这样要吧避免上面所说的那个问题.同时这样也限制了这个工厂的职责,只能创建出课程相关的对象

类图

简单工厂模式在Jdk中的应用

在Jdk中有一个日历类,它创建对象就用到的简单工厂模式

Calendar.getInstance();

在它的getInstance()方法里面有一个createCalendar方法进去看下

public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

Calendar

像这些不就是通过参数分别来创建不同的对象嘛.这里是简单工厂在JDK中的应用.

优缺点及适用场景

适用的场景

– 工厂类创建的对象较少 – 客户端只需传工厂类的参数,对于是如何创建的对象不需要知道

优点:

– 对于用户来说,无需知道其中创建的细节

缺点:

– 工厂类的职责过重,增加新的产品时需要修改工厂类的代码,这个违反的开闭原则 – 对于比较复杂的结构扩展不方便

工厂方法模式

相对于简单工厂模式来说,当简单工厂模式需要修改或者是新增好多的类时,他的职责也就发生了变化,变的很重,这样对于我们维护代码的时候变得不是那么的容易.

工厂方法模式指定义一个创建对象的接口,让实现这个接口的类来决定实例化哪个类,工厂方法模式让类的实例化推迟到子类中进行.

代码

这里我需要定义一个工厂类的抽象层

public interface ICourseFactory {
    ICourse create();
}

分别让JavaCourse和PythonCourse的工厂类来实现他们,完成对象的创建

public class JavaFactory implements ICourseFactory{
    @Override
    public ICourse create() {
        return new JavaCourse();
    }
}

PythonFactory

public class PythonFactory implements ICourseFactory{
    @Override
    public ICourse create() {
        return new PythonCourse();
    }
}

这里每一个工厂类实现了工厂的接口后重写create方法,方法里面写上自已的对象创建逻辑,在使用的时候只需要调用实现子类的create方法即可创建出对应的对象

这样不仅方便维护代码,同时也遵循了单一职责的原则

测试类

public class Test {
    public static void main(String[] args) {
        ICourse iCourse = new JavaFactory().create();
        iCourse.course();
    }

}

适用场景及优缺点

适用场景

– 创建对象需要大量重复代码 – 应用层不依赖于产品类实例如何被创建 实现等细节 – 一个类通过其子类来指定创建哪个对象 

优点

– 用户只需关心所需产品对应的工厂,无须关心创建细节 – 加入新产品符合开闭原则,提高了系统的可扩展性

缺点

– 类的个数容易过多,增加了代码结构的复杂度 – 增加了系统的抽象性和理解难度

抽象工厂模式

抽象工厂模式是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类,也可以称作其他工厂的工厂,它可以在抽象工厂中创建出其他工厂

在此之前应该先了解一个产品族的概念

设计模式之工厂模式详解

产品族:一个工厂有多个产品称为产品族;比如 美的工厂下有空调 冰箱称为美的的产品族

产品等级:N个品牌下的同类型的产品;比如 美的的空调和格力的空调称为一个产品等级

代码

自20年疫情以来,五菱不单单承担了以前造车的行业,也承担起了造口罩.这里所说的五菱的口罩和汽车就属于产品族

ICar

public interface ICar {

}

IMask

public interface IMask {

}

WuLingCar

public class WuLingCar implements ICar{
}

WuLingMask

public class WuLingMask implements IMask{
}

AbstractFactory

public abstract class AbstractFactory {

    public void init(){
        System.out.println("创建对象前的统一处理类");
    }

    abstract ICar createCar();

    abstract IMask createMask();

}

这个AbstractFactory可以使用接口也可以使用抽象类,因为抽象类里面可以写具体的实现,如果有在创建对象前需要处理的逻辑,

WuLingFactory     

public class WuLingFactory extends AbstractFactory {

    @Override
    ICar createCar() {
        return new WuLingCar();
    }

    @Override
    IMask createMask() {
        return new WuLingMask();
    }
}

如果这里要加一个其他的厂商,我只需要继承AbstractFactory,重写里面的方法,创建对应的对象即可

适用场景及优缺点

适用场景

– 应用层不依赖于产品类实现如何被创建,实现细节 – 强调一系列相关的产品对象一起使用创建对象需要大量重复的代码 – 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现

优点

– 具体产品在应用层代码隔离,无须关心创建细节 – 将一个系列产品族统一到一起创建 

缺点

– 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口 – 增加了系统的抽象性和理解难度

今天的文章设计模式之工厂模式详解分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18054.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注