设计模式之工厂模式

前言:

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

一. 工厂模式的简介:

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

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

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

二. 工厂模式实例

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

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.运行结果:

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

三. 工厂模式的适用场景

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

四. 总结:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值