设计模式之工厂方法模式
定义: Define an interface for creating an object,but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法让一个类的实例化延迟到它的子类。
优点:
- 良好的封装性,代码结构清晰,降低模块间的耦合。
- 扩展性较好,可以通过增加产品类来增加产品,或者增加工厂类来增加工厂。
常见应用场景: 可以在所有需要生成对象的地方使用,尤其是复杂度较高的结构里。
工厂方法模式的通用模板:
抽象产品类:负责定义产品的共性,实现抽象的定义,可以通过接口和抽象类实现
/**
* @author: lvshui5u
* @date: 2021/7/18 10:46
* @describe: 抽象产品类 也可以使用接口
*/
public abstract class Product {
/**
* 产品类的公共方法
*/
public abstract void doSomething();
}
具体产品类:继承抽象产品类,实现对产品的定义
public class ConcreteProduct extends Product{
@Override
public void doSomething() {
// 执行的具体业务逻辑
}
}
抽象工厂类:负责定义工厂的共性,实现抽象的定义
public abstract class Factory {
/**
* 生产一个产品
* @param c 该产品的 class
* @param <T> 泛型
* @return a T extends Product
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
具体工厂类:继承抽象工厂类,实现对产品的创建
public class ConcreteFactory extends Factory {
@Override
public <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try {
// 通过类反射找到并创建产品
product = (Product) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)product;
}
}
案例: 一家手机代工厂需要生产两种品牌的手机。
手机的定义
/**
* @author: lvshui5u
* @date: 2021/7/18 11:30
* @describe:
*/
public abstract class Phone {
/**
* 开机
*/
public abstract void open();
/**+
* 打电话
*/
public abstract void call();
/**
* 关机
*/
public abstract void shutdown();
}
两种品牌的手机
public class HuaWei extends Phone{
@Override
public void open() {
System.out.println("HuaWei is opening ...");
}
@Override
public void call() {
System.out.println("HuaWei is calling ...");
}
@Override
public void shutdown() {
System.out.println("HuaWei is shutdown ing ...");
}
}
public class Samsung extends Phone{
@Override
public void open() {
System.out.println("Samsung is opening ...");
}
@Override
public void call() {
System.out.println("Samsung is calling ...");
}
@Override
public void shutdown() {
System.out.println("Samsung is shutdown ing ...");
}
}
手机工厂的定义
public abstract class PhoneFactory {
/**
* 生产手机
* @param c 需要生产哪一款呢
* @param <T> 泛型 是手机就行
* @return 特定手机
*/
public abstract <T extends Phone> T createPhone(Class<T> c);
}
手机工厂的实现
public class ConcretePhoneFactory extends PhoneFactory{
@Override
public <T extends Phone> T createPhone(Class<T> c) {
Phone phone = null;
try {
// 通过类反射找到并创建产品
phone = (Phone) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)phone;
}
}
进行测试
public class Test {
public static void main(String[] args) {
PhoneFactory concretePhoneFactory = new ConcretePhoneFactory();
HuaWei huaWei = concretePhoneFactory.createPhone(HuaWei.class);
huaWei.open();
huaWei.call();
huaWei.shutdown();
System.out.println("=================");
Samsung samsung = concretePhoneFactory.createPhone(Samsung.class);
samsung.open();
samsung.call();
samsung.shutdown();
}
}
结果
HuaWei is opening ...
HuaWei is calling ...
HuaWei is shutdown ing ...
=================
Samsung is opening ...
Samsung is calling ...
Samsung is shutdown ing ...
Process finished with exit code 0
如果该工厂又接到了苹果的订单,则无需改变其他内容,只需要添加一个 Apple 类继承 Phone 抽象类即可。
public class Apple extends Phone{
@Override
public void open() {
System.out.println("Apple is opening ...");
}
@Override
public void call() {
System.out.println("Apple is calling ...");
}
@Override
public void shutdown() {
System.out.println("Apple is shutdown ing ...");
}
}
参考 《设计模式之禅》