创建型模式(Creational Pattern)是对类的实例化过程的抽象化,能够提供对象的创建和管理职责;
创建型模式共有5种:
■ 单例模式;
■ 工厂方法模式;
■ 抽象工厂模式;
■ 建造者模式;
■ 原型模式;
工厂方法模式又叫 虚拟构造函数模式、多态性工厂模式;
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中;
工厂模式可分为:
■ 简单工厂;
一个工厂类处于对产品类实例化的中心位置上,它知道每一个产品,它决定哪一个产品类应当被实例化;
■ 工厂方法;
简单工厂模式的进一步抽象和推广;
■ 抽象工厂模式;
所有形态的工厂模式中最为抽象和最具有一般性的一种形态;
在工厂方法模式中,共涉及以下4个角色:
■ 抽象工厂(Creator)角色:
该角色是工厂方法模式的核心,与应用系统无关,任何在创建对象的工厂类必须实现这个接口;
■ 具体工厂(Concrete Creator)角色:
该角色实现了抽象工厂接口,含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象;
■ 抽象产品(Product)角色:
该角色负责定义产品的共性,实现对产品最抽象的定义;
■ 具体产品(Concrete Product)角色:
该角色实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例;
工厂方法模式的类图如下:
image.png
■ 抽象工厂 Creator.java
public interface Creator {
<T extends Product> T factory(Class<T> c);
}
■ 抽象产品 Product.java
public interface Product {
/**
* 产品类的公共方法
*/
void method1();
void method2();
}
■ 具体工厂 ConcreteCreator.java
public class ConcreteCreator implements Creator{
@Override
public <T extends Product> T factory(Class<T> c) {
Product product = null;
try {
product = (Product) Class.forName(c.getName()).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return (T)product;
}
}
■ 具体产品 ConcreteProduct.java
public class ConcreteProduct implements Product{
@Override
public void method1() {
System.out.println("执行method1");
/**
* 业务逻辑处理代码
*/
}
@Override
public void method2() {
System.out.println("执行method2");
/**
* 业务逻辑处理代码
*/
}
}
■ 应用代码 FactoryMethodDemo.java
public class FactoryMethodDemo {
public static void main(String[] args){
Creator creator = new ConcreteCreator();
Product product = creator.factory(ConcreteProduct.class);
product.method1();
product.method2();
/**
* 继续业务处理
*/
}
}
# 输出:
执行method1
执行method2
工厂方法模式的优点:
■ 良好的封装性,代码结构清晰;
■ 优秀的可扩展性;
■ 屏蔽产品类;
■ 工厂方法模式是典型的解耦框架;
工厂方法模式的使用场景:
■ 工厂方法模式是new一个对象的替代品,因此在所有需要生成对象的地方都可以使用;
但是需要慎重考虑是否需要增加一个工厂类进行管理,增加代码的复杂度;
■ 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式;
■ 工厂方法模式可以用在异构项目中;
例如,通过WebService与一个非Java的项目交互,虽然WebService号称是可以做到异构系统的同构化,但是在实际开发中,还是会碰到很多问题,如类型问题、WSDL文件的支持问题等。从WSDL中产生的对象都认为是一个产品,然后由一个具体的工厂类进行管理,减少与外围的耦合;
■ 工厂方法模式可以使用在测试驱动开发的框架下;
例如,测试一个类 A,就需要将与类A关联的类B也同时产生出来,使用工厂方法模式可以将类B虚拟出来,避免类A与类B的耦合;
■ 工厂方法模式的实例
农场管理系统中,每一种农作物都有专门的园丁管理,形成规模化和专业化生产;
image.png
■ 抽象工厂 FruitGardener.java
public interface FruitGardener {
Fruit factory();
}
■ 抽象产品 Fruit.java
public interface Fruit {
/**
* 生长
*/
void grow();
/**
* 收获
*/
void harvest();
/**
* 栽种
*/
void plant();
}
■ 生产苹果的具体工厂 AppleGardener.java
public class AppleGardener implements FruitGardener{
@Override
public Fruit factory() {
return new Apple();
}
}
■ 生产葡萄的具体工厂 GrapeGardener.java
public class GrapeGardener implements FruitGardener{
@Override
public Fruit factory() {
return new Grape();
}
}
■ 具体产品 - 苹果 Apple.java
public class Apple implements Fruit{
private int treeAge;
public int getTreeAge() {
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
@Override
public void grow() {
System.out.println("苹果正在生长...");
}
@Override
public void harvest() {
System.out.println("收获苹果!");
}
@Override
public void plant() {
System.out.println("栽种苹果!");
}
}
■ 具体产品 - 葡萄 Grape.java
public class Grape implements Fruit{
private boolean seedless;
public boolean isSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
@Override
public void grow() {
System.out.println("葡萄正在生长...");
}
@Override
public void harvest() {
System.out.println("收获葡萄!");
}
@Override
public void plant() {
System.out.println("栽种葡萄!");
}
}
■ 应用场景代码 ClientDemo.java
public class ClientDemo {
public static void main(String[] args){
/**
* 苹果园丁工厂
*/
FruitGardener fruitGardener = new AppleGardener();
/**
* 通过工厂生产苹果
*/
Fruit apple = fruitGardener.factory();
apple.plant();
apple.grow();
apple.harvest();
/**
* 葡萄园丁工厂
*/
fruitGardener = new GrapeGardener();
/**
* 通过工厂生产葡萄
*/
Fruit grape = fruitGardener.factory();
grape.plant();
grape.grow();
grape.harvest();
}
}
# 控制台输出:
栽种苹果!
苹果正在生长...
收获苹果!
栽种葡萄!
葡萄正在生长...
收获葡萄!
参考:
摘录 《设计模式(Java版)》韩敬海主编;(微信读书APP中有资源,可以直接阅读)
网友评论