简单工厂模式
文章目录
- 设计模式太难学?
- 前言
- 一、工厂方法模式
- 二、简单工厂和工厂方法之间的区别
- 简单工厂模式
- 工厂方法模式
- 总结
- 简单工厂模式:
- 工厂方法模式:
前言
之前学习了简单工厂模式,发现如果工厂要新增生产对象的话,就得修改工厂类,但这样就违背了开闭原则。为了解决这一问题,便衍生了下面这一个工厂方法模式。
一、工厂方法模式
先思考一个问题。当你的类、方法写的很复杂很不好扩展的时候应该如何解决?
答:抽它!把一些可能公共的逻辑抽象起来。
这里是一样的道理,工厂方法模式在简单工厂模式的基础上,将工厂类进行抽象,根据依赖倒置的原则,客户端(调用方)只需要跟抽象的工程接口打交道,运行时再根据真正需调用的实现传入并完成调用
二、简单工厂和工厂方法之间的区别上面单纯的文字说明工厂方法模式有点模糊,下面直接放代码来解释
简单工厂模式先创建客户端类、产品抽象接口、具体产品实现类、工厂类 这四个角色的类或接口:
产品相关
//产品抽象接口
public interface Product {
void make();
}
//产品实现类-phone
public class Phone implements Product{
@Override
public void make() {
System.out.println("生产一部手机");
}
}
//产品实现类-computer
public class Computer implements Product{
@Override
public void make() {
System.out.println("生产了一台电脑");
}
}
工厂类
public class ProductFactory {
public static Product createProduct(String product){
if ("phone".equals(product)){
return new Phone();
}
if ("computer".equals(product)){
return new Computer();
}
return null;
}
}
客户端类
public class Client {
public static void main(String[] args) {
//通过工厂类创建“phone”产品
Product phone = ProductFactory.createProduct("phone");
phone.make();
//通过工厂类创建“computer”产品
Product computer = ProductFactory.createProduct("computer");
computer.make();
}
}
运行结果
上面就是一个简单工厂模式的demo。客户端类通过传入不同的参数调用工厂类的方法,从而得出不同的产品对象。
目前工厂类ProductFactory里只生产两种产品:phone和computer。如果我后期想新增一个watch的产品,就得修改工厂类,去实现watch逻辑的添加
public static Product createProduct(String product){
if ("phone".equals(product)){
return new Phone();
}
if ("computer".equals(product)){
return new Computer();
}
//新增
if ("watch".equals(product)){
return new Watch();
}
return null;
}
这样因为加一个产品而去修改工厂类,其实不符合设计模式的开闭原则:对新增开放,对修改关闭。
工厂方法模式看下工厂方法模式是怎样的。它有以下几个角色:客户端类、产品抽象接口、产品实现类、工厂抽象接口、工厂实现类
工厂方法模式较之简单工厂模式的区别就在于对工厂的抽象。
产品相关
//产品抽象接口
public interface Product {
void make();
}
//产品实现类-phone
public class Phone implements Product{
@Override
public void make() {
System.out.println("生产一部手机");
}
}
//产品实现类-computer
public class Computer implements Product{
@Override
public void make() {
System.out.println("生产了一台电脑");
}
}
工厂相关
//抽象出来的工厂接口
public interface AbstractFactory {
Product createProduct();
}
//创建phone产品的工厂类
public class PhoneFactory implements AbstractFactory{
@Override
public Product createProduct() {
return new Phone();
}
}
//创建computer产品的工厂类
public class ComputerFactory implements AbstractFactory{
@Override
public Product createProduct() {
return new Computer();
}
}
客户端类
public class Client {
public static void main(String[] args) {
//拿到工厂类(真正开发中,为了符合开闭原则,客户端类一般都是通过反射方式创建工厂对象,通过配置文件配置某一工厂实现类标识,代码运行时去读取配置,通过反射生成AbstractFactory,再完成调用)
AbstractFactory phoneFactory = new PhoneFactory();
//创建产品
phoneFactory.createProduct().make();
AbstractFactory computerFactory = new ComputerFactory();
//创建产品
computerFactory.createProduct().make();
}
}
说明一下:真正开发中,为了符合开闭原则,客户端类一般都是通过反射方式创建工厂对象,通过配置文件配置某一工厂实现类标识,代码运行时去读取配置,通过反射生成AbstractFactory,再完成调用
运行结果
跟简单工厂模式达到了同样的运行效果,现在假如说需要添加一个watch的产品。只需要实现一个WatchFactory实现AbstractFactory抽象工厂即可。
新增watch产品改造
//新增watch产品类
public class WatchProduct implements Product{
@Override
public void make() {
System.out.println("生产了一条手表");
}
}
//新增watch产品工厂类,实现AbstractFactory接口
public class WatchFactory implements AbstractFactory{
@Override
public Product createProduct() {
return new WatchProduct();
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
//拿到工厂类(真正开发中,为了符合开闭原则,客户端类一般都是通过反射方式创建工厂对象,通过配置文件配置某一工厂实现类标识,代码运行时去读取配置,通过反射生成AbstractFactory,再完成调用)
AbstractFactory phoneFactory = new PhoneFactory();
//创建产品
phoneFactory.createProduct().make();
AbstractFactory computerFactory = new ComputerFactory();
//创建产品
computerFactory.createProduct().make();
AbstractFactory watchFactory = new WatchFactory();
//创建产品
watchFactory.createProduct().make();
}
}
运行效果
可以看到,在我们客户端需要新增wtach产品创建时,只是新增了对应的产品类和产品工厂类。并未修改之前的任何代码。这样就做到了良好的可扩展性,在不修改已有代码的基础上新增新的功能代码。工厂方法模式就很符合开闭原则。
工厂和产品是1对多的关系,一个工厂类创建多个产品。需新增产品时则需修改工厂类
虽然帮我们解耦,把对象的创建和使用分离开来。但是由于其不符合开闭原则,不方便扩展。所以可用性极差。不推荐使用。
简单总结:有解耦的特点(所有工厂模式都有的特点)但不符合设计模式的开闭原则,不建议使用
工厂方法模式:工厂和产品是1对1的关系,一个工厂类创建一个产品,符合单一原则。且在需要新增产品时,则新增其对应的产品工厂类即可。不修改原有代码,符合开闭原则。
工厂方法模式是目前工厂模式中运用最广泛的一种,但工厂方法模式也有其一定的缺点,由于一个产品对应一个工厂类,如果产品种类多的时候,对应的产品工厂类也会增多。这样就加大了系统的开销,因为jvm需要编译加载这些工厂类。
简单总结:符合设计模式单一原则、开闭原则。目前大多流行使用。但容易造成类的个数增加,会造成一定的系统额外开销(适用于被创建的产品种类不多的情况)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)