设计模式之工厂模式

xiaoxiao2021-02-28  22

前言:

工厂模式是对简单工厂的改进,避免对增加新的需求对象时,不断地修改工厂类,但也没有封闭修改,而是将修改的地方转移到了客户端。

一. 工厂模式的简介:

工厂模式:定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法将类的实例化延迟到了子类中。

工厂模式和简单工厂模式的对比:工厂克服了简单工厂违背的开放——封闭原则,又保持了简单工厂封装对象的创建过程的优点

工厂模式的缺点:每增加一个产品,都要增加一个产品的工厂类,增加了代码的开发量。

二. 工厂模式实例

案例:学生和社区志愿者学习雷锋做好事,帮人洗衣、扫地、做饭。

UML模型图: 1. 雷锋类(产品的抽象类):

//雷锋类 package com.factory.product; public abstract class Leifeng { public void wash(){ System.out.println("帮群众洗衣服"); } public void cook(){ System.out.println("帮群众做饭"); } public void sweep(){ System.out.println("帮群众扫地"); } }

2.雷锋的所有的学习者类(产品类):

里氏替换原则

定义:子类必须能替换掉它的父类型。

例:鸵鸟、企鹅就不能继承鸟类,因为它们不会飞,不能完全替换掉它们的父类型。

解释: - 只有完全的替换掉父类型,父类才能重复利用,而子类可以在父类的基础上增加新行为。

每个产品继承父类(雷锋类),就具备类父类的方法和属性。也就学会了雷锋的技能:洗衣、做饭、扫地。

这里体现出面向对象编程中的继承的使用,继承要符合里氏替换原则。

学生类(产品):

package com.factory.impl; import com.factory.product.Leifeng; //学生学雷锋 public class Student extends Leifeng { // 自动学会雷锋的技能 }

社区志愿者类(产品):

package com.factory.impl; import com.factory.product.Leifeng; /** * 志愿者学雷锋 * @author 葫芦娃 * */ public class Volunteer extends Leifeng { // 自动学会雷锋的技能 }

3.工厂抽象类:

抽象类的作用:为了应对变化(如增加新需求),就创建抽象来隔离以后发生的同类变化。

工厂的抽象类,根据需求的新增,创建新的工厂,再用工厂创建对象,避免了影响其他工厂。

依赖倒转原则:

定义:抽象不应该依赖细节,而细节应该依赖抽象。

解释:程序要做针对接口的编程,而不是针对实现的编程。

例:CPU、硬盘、内存条都是对接口的设计。

遵守原则:高层模块不应依赖底层模块。他们都应该依赖抽象。

例:如果程序依赖Oracle的连接实现包,当数据库改成SQLserver后,程序需要修改依赖包,这样就不好。应该做到一个对象依赖对象的变化,不要影响它本身。 如果依赖了底层,底层发生了修改,高层就不能用了。

面向对象的设计中的应用:依赖倒转是面向对象的设计的标志,编码时考虑如何针对抽象编程而非针对细节,所有依赖都止于抽象、类或接口。

package com.factory.Factory; import com.factory.product.Leifeng; /** * 雷锋工厂 * @author 葫芦娃 * */ public interface IFactory { Leifeng createLeifeng(); }

4.工厂实现类之学生工厂类(产品工厂类):

每个产品(对象),都由其独有的工厂负责创建。每个工厂都实现自同一个工厂的抽象类,体现出面向对象中的多态。

学生工厂类:

package com.factory.Factory; import com.factory.impl.Student; import com.factory.product.Leifeng; /** * @author 葫芦娃 * */ public class StudentFactory implements IFactory { @Override public Leifeng createLeifeng() { return new Student(); } }

社区工作者工厂类:

package com.factory.Factory; import com.factory.impl.Volunteer; import com.factory.product.Leifeng; /** * @author 葫芦娃 * */ public class VolunteerFactory implements IFactory { @Override public Leifeng createLeifeng() { return new Volunteer(); } }

5.客户端的调用:

通过工厂的抽象类(IFactory)创建出具体的工厂实例(StudentFactory),再通过这个工厂,创建出对象。

在简单工厂模式中,需要客户端向工厂类中传入参数,去控制对象的创建;而在工厂模式中,如需修改创建对象,在客户端中就可以控制了,只需要将new StudentFactory()改成VolunteerFactory()就可以了。

如果新增一个产品对象,需要增加一个工厂类和一个产品类就可以了,不需要修改原来的工厂类。

package com.factory.client; import com.factory.Factory.IFactory; import com.factory.Factory.StudentFactory; import com.factory.Factory.VolunteerFactory; import com.factory.product.Leifeng; public class Client { public static void main(String[] args) { System.out.println("************学生学雷锋************"); IFactory studentFactory= new StudentFactory(); Leifeng studentLearner = studentFactory.createLeifeng(); studentLearner.sweep(); studentLearner.cook(); studentLearner.wash(); System.out.println("**********社区志愿者学雷锋**********"); IFactory volunteerFactory= new VolunteerFactory(); Leifeng volunteerLearner = volunteerFactory.createLeifeng(); volunteerLearner.sweep(); volunteerLearner.cook(); volunteerLearner.wash(); } }

6.运行结果:

************学生学雷锋************ 帮群众扫地 帮群众做饭 帮群众洗衣服 **********社区志愿者学雷锋********** 帮群众扫地 帮群众做饭 帮群众洗衣服

三. 工厂模式的适用场景

系统不依赖于产品类被创建的细节。系统至少有一个产品族(多个产品)。系统不依赖产品接口实现的细节。

四. 总结:

工厂模式把简单工厂的内部逻辑判断,转移到了客户端。如果新增一项功能,原来是修改工厂类,现在是修改客户端。

工厂模式是简单工厂模式进一步抽象和推广,工厂模式利用了多态,保持了简单工厂通过封装隐藏对象创建过程的优点,也克服了简单工厂违反开放-封闭的缺点。但是工厂模式也因每增加一个产品,就要增加一个产品对应的工厂类,增加了代码开发量。

转载请注明原文地址: https://www.6miu.com/read-850157.html

最新回复(0)