文章目录
1、创建型模式的特点
创建型模式关注的是“怎样创建对象”,特点是“将对象的创建与使用分离”。
这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,并不需要知道商品是怎么生产出来的,因为它们由专门的厂商生产。
2、工厂方法模式的定义
工厂方法(FactoryMethod)模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。
这满足创建型模式中所要求的“创建与使用相分离”的特点。
我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。
如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典[设计模式],它的缺点是增加新产品时会违背“开闭原则”。
本节介绍的“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
3、工厂方法模式的特点
优点:
1、用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
2、在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
4、工厂方法模式的应用场景
1、客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
2、创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
3、客户不关心创建产品的细节,只关心产品的品牌。
5、工厂方法模式的结构
工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成。
抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
6、工厂方法模式的扩展-简单工厂模式
简单工厂模式即静态工厂方法模式
当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式,只包含3个要素:工厂类角色、抽象产品角色、具体产品角色。
7、工厂方法模式的实现-含简单工厂模式实现
7.1 简单工厂模式示例
抽象产品类Car.java:
package com.example.designpattern.simplefactory;
/**
* 抽象产品角色
* Created by Administrator on 2019/10/30.
*/
public abstract class Car {
public abstract void drive();
}
具体产品类Benz.java:
package com.example.designpattern.simplefactory;
import android.util.Log;
/**
* 具体产品角色
* @author Administrator
* @date 2019/10/30
*/
public class Benz extends Car {
@Override
public void drive() {
System.out.println("奔驰汽车在狂奔");
}
}
具体产品类BMW.java:
package com.example.designpattern.simplefactory;
import android.util.Log;
/**
* 具体产品角色
* @author Administrator
* @date 2019/10/30
*/
public class BMW extends Car {
@Override
public void drive() {
System.out.println("宝马汽车在狂奔");
}
}
工厂类Factory.java:
package com.example.designpattern.simplefactory;
/**
* 工厂角色
*
* @author Administrator
* @date 2019/10/30
*/
public class Factory {
public static Car create(int type) {
if (1 == type) {
return new Benz();
} else if (2 == type) {
return new BMW();
} else {
return null;
}
}
}
客户端调用类Client.java:
package com.example.designpattern.simplefactory;
/**
* @author Administrator
* @date 2019/10/30
* 客户端调用类
*/
public class Client {
public static void main(String[] args) {
Car car1 = Factory.create(1);
assert car1 != null;
car1.drive();
Car car2 = Factory.create(2);
assert car2 != null;
car2.drive();
}
}
为了解决简单工厂模式无法新增产品的弊端,我们改进下,在工厂类中,使用类的反射机制来增加产品,见Factory2.java:
package com.example.designpattern.simplefactory;
/**
* 工厂角色
*
* @author Administrator
* @date 2019/10/30
*/
public class Factory2 {
/**
* 根据类的反射机制,传入包名,生成对应的类,可以规避简单工厂模式无法新增产品的缺点
*/
public static Car create(String className) {
try {
Car car=(Car) Class.forName(className).newInstance();
return car;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} catch (InstantiationException e) {
e.printStackTrace();
return null;
}
}
}
此时,我们新增一个产品,即QQ.java:
package com.example.designpattern.simplefactory;
/**
* 具体产品角色-新增产品
* @author Administrator
* @date 2019/11/1
*
* 简单工厂模式缺点:
* 当要新增QQ汽车时,工厂类Factory也必须修改,否则无法new出新的
*/
public class QQ extends Car {
@Override
public void drive() {
System.out.println("QQ汽车在狂奔");
}
}
最后,我们要改进Client.java类:
package com.example.designpattern.simplefactory;
/**
* @author Administrator
* @date 2019/10/30
* 客户端调用类
*/
public class Client {
public static void main(String[] args) {
Car car1 = Factory.create(1);
assert car1 != null;
car1.drive();
Car car2 = Factory.create(2);
assert car2 != null;
car2.drive();
System.out.println("------------");
//传入包名,使用类的反射机制增加新产品
Car c1 = Factory2.create("com.example.designpattern.simplefactory.Benz");
Car c2 = Factory2.create("com.example.designpattern.simplefactory.QQ");
assert c1 != null;
c1.drive();
assert c2 != null;
c2.drive();
}
}
最终测试结果如下:
7.2 工厂方法模式示例
抽象产品类Car.java:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 抽象产品角色
*/
public abstract class Car {
public abstract void drive();
}
抽象工厂类Factory.java:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 抽象工厂角色
*/
public abstract class Factory {
public abstract Car createCar();
}
具体产品类Benz.java:
package com.example.designpattern.factorymethod;
/**
* 具体产品
* @author Administrator
* @date 2019/11/25
*/
public class Benz extends Car {
@Override
public void drive() {
System.out.println("奔驰在飞奔");
}
}
具体工厂类BenzFactory.java:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 具体工厂角色
*/
public class BenzFactory extends Factory {
@Override
public Car createCar() {
return new Benz();
}
}
具体产品BMW.java:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 具体产品
*/
public class BMW extends Car {
@Override
public void drive() {
System.out.println("宝马在飞奔");
}
}
具体工厂BMWFactory.java:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 具体工厂角色
*/
public class BMWFactory extends Factory {
@Override
public Car createCar() {
return new BMW();
}
}
客户端调用类:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 客户端调用类
*/
public class Client {
public static void main(String[] args){
Car benz=new BenzFactory().createCar();
benz.drive();
Car bmw=new BMWFactory().createCar();
bmw.drive();
}
}
当增加新产品时,只需要新增一个具体产品类和一个具体工厂类,如
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 具体产品-增加新产品QQ时,只需要扩展出一个对应的工厂即可,即QQFactory
*/
public class QQ extends Car {
@Override
public void drive() {
System.out.println("QQ在慢行");
}
}
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 具体工厂角色-新增产品
*/
public class QQFactory extends Factory {
@Override
public Car createCar() {
return new QQ();
}
}
调用时,只需增加新产品调用即可:
package com.example.designpattern.factorymethod;
/**
* @author Administrator
* @date 2019/11/25
* 客户端调用类
*/
public class Client {
public static void main(String[] args){
Car benz=new BenzFactory().createCar();
benz.drive();
Car bmw=new BMWFactory().createCar();
bmw.drive();
//增加新产品
Car qq=new QQFactory().createCar();
qq.drive();
}
}
测试结果:
8、工厂方法模式知识问答
1、关于工厂方法,以下叙述不正确的是(C)
A、Factory Method 是一个用于帮助分配创建的责任的模式。
B、Factory Method 模式和 Abstract Factory 模式总是配合使用
C、Factory Method 适用于将对象实例化的规则推迟到某个派生类的情形
D、Factory Method 是属于创建型模式。
2、Factory Method(工厂方法)模式的意图是(A)
A、定义一个用于创建对象的接口,让子类决定实例化哪一个类。将实例化延迟到其子类
B、为一个对象动态连接附加的职责
C、你希望只拥有一个对象,但不用全局对象来控制对象的实例化
D、定义一个操作中的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算 法的某些特定步骤
3、下列关于静态工厂与工厂方法表述错误的是(A)
A、两者都满足开闭原则:静态工厂以 if else 方式创建对象,增加需求的时候会修改源代码
B、静态工厂对具体产品的创建类别和创建时机的判断是混和在一起的,这点在工厂方法是分开的
C、不能形成静态工厂的继承结构
D、在工厂方法模式中,对于存在继承等级结构的产品树,产品的创建是通过相应等级结构的工厂创建的
9、工厂方法模式PPT素材
微信公众号: TechU