快捷搜索:  汽车  科技

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼可以看到Shape工厂要负责多个Shape了,就回归到简单工厂,一个工厂处理多个产品(需要传字符串名字然后if-else)如何找到产品类工厂?相当于产品类工厂也需要有人来创造他,又是处理多个产品的工厂类,我们叫他FactoryProducer每个产品对应一个工厂类,然后同一类的产品,比如都是水果类,则再抽象一个水果工厂出来,具体的工厂类去实现他的create方法package com.melo.mydesign.Factory.FactoryMethod.Product; //产品只关心使用 不关心创建 public interface Fruit { void eat(); } 水果具体子类package com.melo.mydesign.Factory.FactoryMethod.Product; public class Apple implements Fruit {

前言

每每谈及到Java,就不免会想到一个悲伤的事实:你是否每天都在new对象,却依然坚守在单身岗上屹立不倒。(所谓面向对象编程的"缺点"hhh),这篇来学一下工厂模式,摆脱new对象的苦恼!

知识点传统工厂
  • 抽象类和子类们
  • 生产和使用放在一起了没有分离开,使用时传名字,然后来生产相应的产品

public class OrderPizza { // 构造器 public OrderPizza() { Pizza pizza = null; String orderType; // 订购披萨的类型 orderType = getType(); if (orderType.equals("greek")) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 "); } else if (orderType.equals("cheese")) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 "); } else if (orderType.equals("pepper")) { pizza = new PepperPizza(); pizza.setName("胡椒披萨"); } else { break; } //输出pizza 制作过程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } 改进的思路分析分析

  • 修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizza的代码,往往有多处。
  • 思路:把创建Pizza对象封装到一个工厂类中,这样我们有新的Pizza种类时,只需要修改该工厂类就好,其它有创建到Pizza对象的代码就不需要修改了.->简单工厂模式
简单工厂模式(传产品名字然后if-else)

一个超级工厂,负责生产所有种类的产品

  • 在传统工厂的基础上,通过将产品创建的过程封装成一个工厂类,实现生产和使用分离开
接口类/抽象类

package com.melo.design.工厂模式.简单工厂模式; public interface Shape { void draw(); } 子类产品

package com.melo.design.工厂模式.简单工厂模式; public class Circle implements Shape{ @Override public void draw() { System.out.println("Circle"); } } 工厂类

package com.melo.design.工厂模式.简单工厂模式; public class ShapeFactory { public static Shape getShape(String shape){ if("Circle".equals(shape)){ return new Circle(); }else if("Triangle".equals(shape)){ return new Triangle(); } return null; } } 调用方

package com.melo.design.工厂模式.简单工厂模式; public class Main { public static void main(String[] args) { Shape circle = ShapeFactory.getShape("Circle"); circle.draw(); } } 缺点

总而言之,简单工厂模式就是让一个工厂类承担构建所有对象的职责。调用者需要什么产品,让工厂生产出来即可。它的弊端也显而易见:

  • 一是如果需要生产的产品过多,此模式会导致工厂类过于庞大,承担过多的职责,变成超级类。当苹果生产过程需要修改时,要来修改此工厂。梨子生产过程需要修改时,也要来修改此工厂。也就是说这个类不止一个引起修改的原因。违背了单一职责原则
  • 二是当要生产新的产品时,必须在工厂类中添加新的分支。而开闭原则告诉我们:类应该对修改封闭。我们希望在添加新功能时,只需增加新的类,而不是修改既有的类,所以这就违背了开闭原则
工厂方法模式
  • 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
  • 工厂方法让类的实例化推迟到子类中进行!!!

原本简单工厂是一个工厂,负责生产所有的产品,现在要改成每个对象对应一个工厂,一个工厂只负责生产一个产品

优点
  • 这样我们就解决了上文所述的单一职责问题,每个工厂只负责生产一个产品
  • 同时也解决了开闭原则,每次需要新增一个产品的时候,我们只需要新增一个工厂类就好,而不需要去修改原来的工厂类
缺点
  • 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

每个产品对应一个工厂类,然后同一类的产品,比如都是水果类,则再抽象一个水果工厂出来,具体的工厂类去实现他的create方法

MyDemo

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(1)

水果接口

package com.melo.mydesign.Factory.FactoryMethod.Product; //产品只关心使用 不关心创建 public interface Fruit { void eat(); } 水果具体子类

package com.melo.mydesign.Factory.FactoryMethod.Product; public class Apple implements Fruit { @Override public void eat() { System.out.println("吃苹果"); } }

package com.melo.mydesign.Factory.FactoryMethod.Product; public class Pear implements Fruit { @Override public void eat() { System.out.println("吃梨子"); } } 水果工厂接口

package com.melo.mydesign.Factory.FactoryMethod.Factory; import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit; public interface FruitFactory { Fruit createFruit(); } 具体水果工厂实现子类

package com.melo.mydesign.Factory.FactoryMethod.Factory; import com.melo.mydesign.Factory.FactoryMethod.Product.Apple; import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit; public class AppleFactory implements FruitFactory { @Override public Fruit createFruit() { return new Apple(); } }

package com.melo.mydesign.Factory.FactoryMethod.Factory; import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit; import com.melo.mydesign.Factory.FactoryMethod.Product.Pear; public class PearFactory implements FruitFactory { @Override public Fruit createFruit() { return new Pear(); } } 具体使用

package com.melo.mydesign.Factory.FactoryMethod; import com.melo.mydesign.Factory.FactoryMethod.Factory.AppleFactory; import com.melo.mydesign.Factory.FactoryMethod.Factory.FruitFactory; import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit; public class Consumer { public static void main(String[] args) { //使用者不需要知道是哪个类在生产 面对的都是 FruitFactory 这个接口 FruitFactory appleFactory = new AppleFactory(); Fruit apple = appleFactory.createFruit(); apple.eat(); } } 抽象工厂模式

  • 工厂方法模式,随着产品越来越多,会产生越来越多的产品类和产品工厂,能不能把一类产品,抽离出来变成一个产品家族呢?

这意味着不再是每一个产品就对应一个产品工厂了
而是一类产品,对应一个产品类工厂

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(2)


以菜鸟的为例子(感觉比较权威一点)

UML
  • 首先从使用者的角度,要生产一个产品,一开始肯定是先找到那个产品所在的产品类工厂

如何找到产品类工厂?相当于产品类工厂也需要有人来创造他,又是处理多个产品的工厂类,我们叫他FactoryProducer

  • 然后拿到具体的产品类工厂了,就要生产具体的产品,处理方式同上(if-else)
    • 剩下的就是产品和父类产品了,具体实现代码见下方

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(3)

可以看到Shape工厂要负责多个Shape了,就回归到简单工厂,一个工厂处理多个产品(需要传字符串名字然后if-else)

抽象工厂和具体产品类工厂(注意需要把工厂类的方法都定义出来)

具体实现看子类

  • 可以看到Shape产品类工厂,也得实现Color的方法,只不过return null罢了

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(4)

同时,FactoryProducer也得处理多个,既要处理Shape也要处理Color具体使用

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(5)

MyDemo

打工仔适合打造个人ip吗?工厂模式--摆脱你日复一日new对象却依旧单身的苦恼(6)

抽象产品类工厂

package com.melo.mydesign.Factory.AbstractFactory.Factory; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit; public interface AbstractFactory { Fruit createFruit(String fruitName); Car createCar(String carName); } 具体产品类工厂--Car

package com.melo.mydesign.Factory.AbstractFactory.Factory; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Audi; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.BMW; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit; public class CarFactory implements AbstractFactory{ @Override public Fruit createFruit(String fruitName) { return null; } public Car createCar(String carName){ if(carName.equalsIgnoreCase("BMW")){ return new BMW(); }else if(carName.equalsIgnoreCase("Audi")) { return new Audi(); } return null; } } 具体产品类工厂--Fruit

package com.melo.mydesign.Factory.AbstractFactory.Factory; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Pear; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Apple; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit; public class FruitFactory implements AbstractFactory { public Fruit createFruit(String fruitName){ if(fruitName.equalsIgnoreCase("Apple")){ return new Apple(); }else if(fruitName.equalsIgnoreCase("Pear")) { return new Pear(); } return null; } @Override public Car createCar(String carName) { return null; } } FactoryProducer--负责生产产品类工厂的对象

package com.melo.mydesign.Factory.AbstractFactory.Factory; public class FactoryProducer { public static AbstractFactory produceFactory(String factoryName){ if(factoryName.equalsIgnoreCase("Fruit")){ return new FruitFactory(); }else if (factoryName.equalsIgnoreCase("Car")){ return new CarFactory(); } return null; } } Car类产品接口

package com.melo.mydesign.Factory.AbstractFactory.Product.Car; //产品只关心使用 不关心创建 public interface Car { void eat(); } Car类产品实现类

package com.melo.mydesign.Factory.AbstractFactory.Product.Car; public class BMW implements Car { @Override public void eat() { System.out.println("宝马"); } } Fruit类产品

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit; //产品只关心使用 不关心创建 public interface Fruit { void eat(); } Fruit类实现类

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit; import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit; public class Pear implements Fruit { @Override public void eat() { System.out.println("吃梨子"); } } 消费者

package com.melo.mydesign.Factory.AbstractFactory; import com.melo.mydesign.Factory.AbstractFactory.Factory.AbstractFactory; import com.melo.mydesign.Factory.AbstractFactory.Factory.FactoryProducer; import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car; public class Consumer { public static void main(String[] args) { AbstractFactory carFactory = FactoryProducer.produceFactory("Car"); Car bmw = null; if (carFactory != null) { bmw = carFactory.createCar("BMW"); } if (bmw != null) { bmw.eat(); } } } 缺点

  • 不再符合开闭原则了,因为本质是由简单工厂去升级而来的,又回归到了一个产品类工厂,需要处理多个产品的问题,**就需要if-else了 **
总结
  • 一个小小的工厂模式,就把前边学到的几大原则: 开闭原则 ,依赖倒转原则(善用抽象接口而不是具体实现) 体现得淋漓尽致.产品一旦多起来,就要抽离出一个抽象的产品类接口,让子类去实现他,使用者只关心抽象,而不关心具体的实现,不需要知道具体的类名,想生成苹果就直接 Fruit apple = new Apple(); 而不用 Apple apple = new Apple();而如果生产的过程变得复杂起来,比如苹果还需要各种处理,就需要将创建的过程封装起来,不暴露给使用者,这时就需要用到专门的工厂类来进行包装了,外界只需要从工厂里边拿就好了,传一个简单的"苹果"字符串,这就演变到了简单工厂模式了
  • 再然后我们发现一个简单工厂类,名曰简单,但是却要处理各种各样的产品,每次新增一个产品,都得去修改if-else代码块,不符合开闭原则
    • 由此引入了 工厂方法模式 让每一个产品就去对应有一个产品工厂,专门的工厂来生产产品,一个工厂只负责一个产品的生成,满足了单一职责原则,同时每次新增产品,只需要多加一个产品工厂就好了,无需修改原来的工厂,又解决了开闭原则的问题
  • 然而,随着产品数量越来越大,单纯一个工厂负责一个产品的话,工厂的数量也许会越来越多,而且,这些产品之前可能存在某些联系,比如都是水果类,那我们何不抽离出一个水果工厂,来生产各式各样的水果呢

看到这里可能有细心的读者就发现了,一个工厂又要去负责生产多个产品了,那似乎又回到了简单工厂模式,不符合开闭原则和单一职责了,是的,抽象工厂模式其实就是简单工厂的升级版而已!

猜您喜欢: