设计模式(1)——工厂模式


概述

尝试理解以下概念,有助于学习工厂模式。

产品族:一个或多个具有相同特征关联产品的集合。

简单工厂 一个总工厂,可以生产任意产品族的产品。

工厂方法 :将总工厂进行细分,不同类型工厂,生产其对应产品族的一个类型产品。

抽象工厂:不同类型的工厂,生产其对应产品族的多个类型产品。

简单工厂模式

注意:简单工厂模式不属于GoF设计模式
定义:工厂根据传入的参数即可返回客户所需的对象,客户而不需要知道具体类的类名字。客户端只需传入相应的参数,就可以得到相应的对象实例,并不关心工厂是如何进行创建实现的。
适用:仅仅适用于工厂负责创建对象较少的情况下
优点

  • 实现了对责任的分割,它提供了专门的工厂类用于创建对象
  • 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可

缺点

  • 工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

实例说明
通过CourseFactory,来通过传入参数创建并返回对应的课程实例。
ICouse为课程接口,所有课程都得实现这个接口。

模式结构和其设计图如下
工厂角色:CourseFactory
抽象产品:ICourse
具体产品:JavaCourese、PythonCourse
在这里插入图片描述

代码:

ICourse

public interface ICourse {
    void record();
}

JavaCourese

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

PythonCourse

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

CourseFactory

public class CourseFactory {
    //缺点:业务拓展的话 不能满足开闭原则 如果增加课程就得对源代码进行else if 修改。 
	//修改源代码 不可取
    public ICourse create1(String name)
    {
        if(name.equals("Java"))
        {
            return new JavaCourse();
        }
        else if(name.equals("Python"))
        {
            return new PythonCourse();
        }
        else
            return null;
    }
    //优点:通过反射机制 动态灵活性好
    //缺点:参数为字符串可控性不好 继续优化
    public ICourse create2(String classname)
    {
        if(!(classname==null||classname.equals("")))
        {
            try {
                return (ICourse)Class.forName(classname).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
            return null;
    }
	//参数采用泛型 为上界限通配符 所有继承接口ICounse的类或接口均可作为参数
    public ICourse create(Class<? extends ICourse> c)
    {
        if(c!=null)
        {
            try {
                return c.newInstance();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

SimpleFactoryTest

public class SimpleFactoryTest{
    public static void main(String[] args) {
       CourseFactory factory=new CourseFactory();
       //创建Java课程
       factory.create(JavaCourse.class).record();
       factory.create(PythonCourse.class).record();
       factory.create(WebCourse.class).record();
    }
}

工厂方法模式

定义:属于类创建型模式。此模式中,将工厂职责进行细分。工厂父类负责定义创建产品对象的公共接口,工厂子类负责实现接口生产具体的物品。工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。实现开闭原则和单一职责
使用情况

  1. 客户类不需要知道具体产品类的类名,只需要知道所对应的工厂即可。
  2. 一个类通过其子类来指定创建哪个对象,抽象工厂类提供创建产品的接口,子类具体实现。

优点

  1. 封装了产品对象具体的创建细节。
  2. 符合开闭原则,具有良好的扩展性。添加新的产品族时,只需要加一个具体工厂和具体产品就行。
  3. 符合单一职责。

缺点
添加新产品时,需要编写新的具体产品类和与之对应的工厂类。增加了系统的复杂度,有了更多的类需要编译和运行,给系统带来了额外的开销。

举例说明
将CourseFactory职责细分,创建ICourseFactory父接口。
具体实现则是,PythonCourseFactory和JavaCourseFactory两个类,分别负责创建Python和Java课程。

模式结构和其结构图:

  • 抽象工厂:ICourseFactory
  • 具体工厂: JavaCourseFactory 、PythonCourseFactory
  • 抽象产品:ICourse
  • 具体产品: JavaCourese、PythonCourse
    在这里插入图片描述
    代码:

ICourseFactory

public interface ICourseFactory {
    ICourse create();
}

不同的工厂根据自身的职责不同,分别实现父接口的方法,创建出不同的对象
JavaCourseFactory

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

PythonCourseFactory

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

Test

public class Test {
    public static void main(String[] args) {
        ICourseFactory javaCourseFactory=new JavaCourseFactory();
        javaCourseFactory.create().record();

        ICourseFactory pythonCourseFactory=new PythonCourseFactory();
        pythonCourseFactory.create().record();
    }
}

抽象工厂模式

定义:抽象工厂模式是工厂方法模式的泛化版本,工厂方法模式是一种特殊的抽象工厂模式。工厂方法模式中,工厂只生产该类型的一个产品,而在抽象工厂模式中,工厂具有了该类型的多个产品功能。

优点

  • 所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需改变具体工厂的创建实例,就可以在某种程度上改变整个软件系统的行为。抽象工厂模式实现了高内聚,低耦合的目的。
  • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族的对象。
  • 增加新的具体工厂和产品族方便,无须修改已有代码,符合开闭原则。

缺点:产品族内部产品的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,这时候抽象工厂需要修改,则几乎所有的具体工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

适用情况

  • 系统不依赖产品类实例如何被创建、组合和表达的细节。
  • 系统中有多于一个的产品族,而每次只使用其中某一产品族。java和python是两个产品族。
  • 属于同一产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。video和note属于一个产品族。

举例说明:本例中对于每个工厂的职责从一个变成了多个职责,Java工厂由最初的生产Java课程变成了生产Java笔记和Java录像多个工作。一个产品族包含了多个产品。

模式结构和图

  • 抽象工厂:ICourseFactory
  • 具体工厂:JavaCourseFactory 、PythonCourseFactory
  • 抽象产品:INote、IVideo
  • 具体产品:JavaNote、JavaVideo、PythonNote、PythonVideo

在这里插入图片描述
代码:

ICourseFactory

public interface ICourseFactory {
    IVideo createVideo();
    INote createNote();
}

JavaCourseFactory

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public IVideo createVideo() {
        return new JavaVideo();
    }

    @Override
    public INote createNote() {
        return new JavaNote();
    }
}

PythonCourseFactory

public class PythonCourseFactory implements ICourseFactory {
    @Override
    public IVideo createVideo() {
        return new PythonVideo();
    }

    @Override
    public INote createNote() {
        return new PythonNote();
    }
}

INote

public interface INote {
    void record();
}

JavaNote

public class JavaNote implements INote {
    @Override
    public void record() {
        System.out.println("Java 笔记");
    }
}

PythonNote

public class PythonNote implements INote {
    @Override
    public void record() {
        System.out.println("Python 笔记");
    }
}

IVideo

public interface IVideo {
    void record();
}

JavaVideo

public class JavaVideo implements IVideo {
    @Override
    public void record() {
        System.out.println("Java video");
    }
}

PythonVideo

public class PythonVideo implements IVideo {
    @Override
    public void record() {
        System.out.println("Python video");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值