#工厂模式
下面例子中鼠标,键盘,耳麦为产品,惠普,戴尔为工厂。
简单工厂模式(静态方法模式)
简单工厂模式不是 23 种里的一种,简而言之,就是有一个专门生产某个产品的类。
比如下图中的鼠标工厂,专业生产鼠标,给参数 0,生产戴尔鼠标,给参数 1,生产惠普鼠标。
组成(角色) | 关系 | 作用 |
---|---|---|
抽象产品(Product) | 具体产品的父类 | 描述产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
工厂(Creator) | 被外界调用 | 根据传入不同参数从而创建不同具体产品类的实例 |
public class DellMouse extends Mouse{
public void show(){
System.out.println("hello,I 'm dell mouse");
}
}
HpMouse
public class HpMouse extends Mouse{
public void show(){
System.out.println("hello,I 'm hp mouse");
}
}
工厂类:
public class MouseFactory {
public static Mouse manufacture(int choose){
switch (choose){
case 0:
return new DellMouse();
case 1:
return new HpMouse();
default:
return null;
}
}
}
Main:
public class Main {
public static void main(String[] args) {
Mouse m = MouseFactory.manufacture(1);
m.show();
}
}
缺点:
1.违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
2.工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响。
工厂模式(工厂方法模式)
工厂模式也就是鼠标工厂是个父类(抽象类)
戴尔鼠标工厂,惠普鼠标工厂继承它,可以分别生产戴尔鼠标,惠普鼠标。
生产哪种鼠标不再由参数决定,而是创建鼠标工厂时,由戴尔鼠标工厂创建。
后续直接调用鼠标工厂.生产鼠标()即可
工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,符合开放封闭原则,克服了简单工厂模式中缺点.
MouseFactory类:
abstract class MouseFactory {
public abstract Mouse manufacture();
}
DellMouseFactory
public class DellMouseFactory extends MouseFactory {
@Override
public Mouse manufacture() {
return new DellMouse();
}
}
HpMouseFactory
public class HpMouseFactory extends MouseFactory {
@Override
public Mouse manufacture() {
return new HpMouse();
}
}
Main
public class Main {
public static void main(String[] args) {
DellMouseFactory df= new DellMouseFactory();
df.manufacture().show();
}
}
抽象工厂模式
工厂方法模式存在一个严重的问题: **一个具体工厂只能创建一类产品** 而在实际过程中,一个工厂往往需要生产多类产品。为了解决上述的问题,我们又使用了一种新的设计模式:抽象工厂模式。抽象工厂模式也就是不仅生产鼠标,同时生产键盘。
也就是 PC 厂商是个父类,有生产鼠标,生产键盘两个接口。
戴尔工厂,惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘,和惠普鼠标+惠普键盘。
创建工厂时,由戴尔工厂创建。
后续工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()则生产戴尔键盘。

步骤1: 创建抽象工厂Factory 类,定义具体工厂的公共接口
public abstract class Factory {
public abstract Mouse manufactureMouse();
public abstract KeyBoard manufactureKeyBoard();
}
步骤2: 创建抽象产品族Product类 ,定义具体产品的公共接口;
public abstract class Product {
public abstract void show();
}
创建抽象产品类Mouse,KeyBoard ,定义具体产品的公共接口
Mouse
public abstract class Mouse extends Product{
public abstract void show();
}
KeyBoard
public abstract class KeyBoard extends Product {
@Override
public abstract void show();
}
创建具体产品类(继承抽象产品类)HpMouse,DellMouse,HpKeyboard,DellKeyboard, 定义生产的具体产品;
HpMouse
public class HpMouse extends Mouse {
public void show(){
System.out.println("hello,I 'm hp mouse");
}
}
DellMouse
public class DellMouse extends Mouse {
public void show(){
System.out.println("hello,I 'm dell mouse");
}
}
HpKeyboard
public class HpKeyBoard extends KeyBoard {
@Override
public void show() {
System.out.println("pili pala...I'm HpKeyBoard!");
}
}
DellKeyboard
public class DellKeyBoard extends KeyBoard {
@Override
public void show() {
System.out.println("pilipala...I'm DellKeyboard!");
}
}
步骤5:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
DellFactory
public class DellFactory extends Factory{
@Override
public Mouse manufactureMouse() {
return new DellMouse();
}
@Override
public KeyBoard manufactureKeyBoard() {
return new DellKeyBoard();
}
}
HpFactory
public class HpFactory extends Factory {
@Override
public Mouse manufactureMouse() {
return new HpMouse();
}
@Override
public KeyBoard manufactureKeyBoard() {
return new HpKeyBoard();
}
}
步骤6:客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
public class Main {
public static void main(String[] args) {
DellFactory df = new DellFactory();
HpFactory hf = new HpFactory();
df.manufactureKeyBoard().show();
df.manufactureMouse().show();
hf.manufactureKeyBoard().show();
hf.manufactureMouse().show();
}
}
在抽象工厂模式中,假设我们需要增加一个工厂
假设我们增加华硕工厂,则我们需要增加华硕工厂,和戴尔工厂一样,继承 PC 厂商。
之后创建华硕鼠标,继承鼠标类。创建华硕键盘,继承键盘类即可。

在抽象工厂模式中,假设我们需要增加一个产品
假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦,惠普耳麦这两个子类。
之后在PC厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂,惠普工厂这两个类中,分别实现生产戴尔耳麦,惠普耳麦的功能。 以上。

参考文章:
抽象工厂模式(Abstract Factory)- 最易懂的设计模式解析
菜鸟教程 抽象工厂模式
#工厂方法创建bean
我们再回顾一下配置Bean
- 配置形式:基于XML文件的方式;基于注解的方式;
- Bean配置方式:通过全类名反射,通过工厂方法(静态工厂方法&实例工厂方法),FactoryBean
有些时候(貌似很少),项目中需要通过工厂方法来创建 Bean 实例。这里的工厂可分为静态工厂和实例工厂。
/**
* 静态工厂方法:直接调用某个类的静态方法,就可以得到一个对象(代替new)
* Created by kaixin on 2018/8/22.
*/
public class StaticCarFactory {
//静态工厂方法
public static Car getCar(String name){
return cars.get(name);
}
private static Map<String,Car> cars = new HashMap<>() ;
static {
cars.put("changan",new Car("changan",23000));
cars.put("changhe",new Car("changhe",12000));
}
}
/**
* 实例工厂方法: 实例工厂的方法,即先创建工厂本身,再调用实例方法返回bean。
* Created by kaixin on 2018/8/22.
*/
public class InstanceCarFactory {
private Map<String,Car> cars =null;
public InstanceCarFactory() {
cars= new HashMap<>();
cars.put("benteng",new Car("benteng",12000));
}
public Car getCar(String name){
return cars.get(name);
}
}
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext actxt = new ClassPathXmlApplicationContext("beans-factory.xml");
Car carone =(Car) actxt.getBean("carone");
Car cartwo =(Car) actxt.getBean("cartwo");
System.out.println(carone);
System.out.println(cartwo);
actxt.close();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过静态工厂方法配置bean -->
<!--class属性指向静态工厂的全类名
factory-method: 指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用该属性传入-->
<bean id="carone" class="com.spring.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="changhe"></constructor-arg>
</bean>
<!--配置工厂的实例 -->
<bean id="carFactory" class="com.spring.factory.InstanceCarFactory" ></bean>
<!--
通过实例工厂方法来配置bean
factory-bean指向实例工厂方法的bean
-->
<bean id="cartwo" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="benteng"></constructor-arg>
</bean>
</beans>
#FactoryBean创建Bean
###应用场景
FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
实现方法
自己写个MyFactoryBean 实现FactoryBean接口
public class CarFactoryBean implements FactoryBean {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public Car getObject() throws Exception {
return new Car(brand,5000000);
}
/**
* 返回bean的类型
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
xml文件中的配置
<!--
通过 FactoryBean配置bean实例
class: 指向FactoryBean的全类名
property: 指向FactoryBean的属性
但实际返回的是FactoryBean的getObject() bean对象
-->
<bean id="car" class="com.spring.factorybean.CarFactoryBean">
<property name="brand" value="BMW"></property>