建议大家不要看我的文章,我写的比较随性,推荐神作地址,通俗易懂:
https://blog.csdn.net/LoveLion/article/details/9319181
https://blog.csdn.net/LoveLion/article/details/9319323
https://blog.csdn.net/LoveLion/article/details/9319423
https://blog.csdn.net/LoveLion/article/details/9319481
https://blog.csdn.net/LoveLion/article/details/9319571
工厂模式一般分为三种:简单工厂模式,工厂方法模式,抽象工厂模式。
工厂模式的诞生:把具体的业务逻辑交由工厂类去完成,程序体本身并不关注这类逻辑的创建和销毁。减少了程序的耦合性和提高了程序的可维护性,符合了程序设计的开闭原则。
简单工厂模式:具体对象的实例由工厂去创建
GOF的23种设计模式并不区分简单工厂模式,和工厂方法模式同属一个模式。
例子:BMW品牌需要生产汽车,汽车的型号为BMW277,BMW520,BMW666。BMW最开始计划按部就班的生产:
public class BMW { public static void main(String[] args) { // 生产BMW277 // 1.组装引擎。 //2.组长轮胎 //3.组长地盘 //生产BMW520 // 1.组装引擎。 //2.组长轮胎 //3.组长地盘 //生产BMW666 // 1.组装引擎。 //2.组长轮胎 //3.组长地盘 } }
就这样一个一个生产完了,突然BMW公司发现,若其中一个环节出问题,其剩下的步骤就无法继续执行,而且若增加新的型号时,必须在生产的主要业务逻辑代码中添加额外的代码,并且所有业务逻辑都放在了一个块中执行,大大的限制了以后生产的灵活性。于是BMW决定建造额外的工厂去专门做这些事,主业务(也就是main方法)去告诉工厂需要什么型号的汽车即可,不参与具体的生产流程
例:
定义一个BMW的抽象类或者接口,所有型号的汽车都必须继承或者实现该类,相当于BMW总部,总部告诉工厂需要生产什么型号的汽车:
public interface BMW { // 组装 public void create(); }
BMW277:
public class BMW277 implements BMW{ @Override public void create() { //组装流程在此进行 } }
BMW520:
public class BMW520 implements BMW{ @Override public void create() { // 组长流程再次进行 } }
BMW666:
public class BMW666 implements BMW{ @Override public void create() { // 组长流程在此进行 } }
创建简单工厂:
public class BMWFactory { public static BMW getBMW(String type){ switch (type) { case "277": return new BMW277(); case "520": return new BMW520(); case "666": return new BMW666(); default: return null; } } }
总部调用工厂方法生产对应型号的汽车:
public class Test { public static void main(String[] args) { // 简单工厂模式 BMW bmw520 = BMWFactory.getBMW("520"); BMW bmw277 = BMWFactory.getBMW("277"); } }
此时若需要增加新的信号,则只需要实现BMW接口,并且在工厂内中增加响应的case分支即可,既不影响主程序main的执行,还对主程序进行了解耦操作。
后来BMW的汽车型号越来越多,如果继续这样增加下去,还需要在工厂类中增加代码,违背了程序的开闭原则,即是禁止修改,提倡扩展。于是BMW想出了更好的办法:
工厂方法模式:
即以前的代码写好后就写好了,不会对以前的代码做任何改动,只需要在之前的代码之上继续扩展即可
例:在以上的基础上推倒已有的工厂,重新建造工厂总部:抽象工厂或者工厂接口:
public abstract class AbstractFactory { public abstract BMW getBmw(); }
然后开分厂,每个分厂负责生产对应的型号的汽车:
生产277的工厂:
public class BMW277Factory extends AbstractFactory{ @Override public BMW getBmw() { return new BMW277(); } }
生产520的工厂:
public class BMW520Factory extends AbstractFactory{ @Override public BMW getBmw() { return new BMW520(); } }
生产666的工厂:
public class BMW666Factory extends AbstractFactory{ @Override public BMW getBmw() { return new BMW666(); } }
每个型号的汽车交友各自的工厂去生产,这样在增加新的型号的汽车时,只需要继承AbstractFactory在创建一个生产对应型号的汽车即可。
这样就符合了程序设计的开闭原则。但是问题又出现了,若之后增加的型号越来越多,则会出现大量的汽车类和汽车工厂,而且此方法无法应对更复杂的业务场景:
BMW决定为每个型号的汽车都分别安装不同型号的空调和行车记录仪,277安装的空调型号为Cool277和行车记录仪Video277,
520安装型号为Cool520和行车记录仪Video520,666同理。于是决定彩用抽象工厂模式:
产品类型:BMW-->BMW277,BMW520,BMW666
Cool ->Cool277,Cool520,Cool666
Video->Video277,Video520,Video666
产品族:BMW277,Cool277,Video277
BMW520,Cool520,Video520
BMW666,Cool666,Video666
同一个工厂可以生成对应型号的产品族即可:
例子:
空调抽象类
public abstract class Cool { }
277空调:
public class Cool277 extends Cool{ }
520空调
public class Cool520 extends Cool{ }
666空调:
public class Cool666 extends Cool{ }
行车记录仪抽象类:
public abstract class Video { }
277:
public class Video277 extends Video{ }
520:
public class Video520 extends Video{ }
666:
public class Video666 extends Video{ }
抽象工厂族:
public abstract class Factory { // 制造汽车 abstract BMW getBmw(); // 制造空调 abstract Cool getCool(); // 制造行车记录仪 abstract Video getVideo(); }
277产品族工厂类:
public class Factory277 extends Factory{ @Override BMW getBmw() { return new BMW277(); } @Override Cool getCool() { return new Cool277(); } @Override Video getVideo() { return new Video277(); } }
520产品族工厂类:
public class Factory520 extends Factory{ @Override BMW getBmw() { return new BMW520(); } @Override Cool getCool() { return new Cool520(); } @Override Video getVideo() { return new Video520(); } }
666产品族工厂类:
public class Factory666 extends Factory{ @Override BMW getBmw() { return new BMW666(); } @Override Cool getCool() { return new Cool666(); } @Override Video getVideo() { return new Video666(); } }
主程序通知工厂制作相关型号汽车和空调:
public class Test { public static void main(String[] args) { // 277型号产品族 Factory factory277 = new Factory277(); BMW bmw277 = factory277.getBmw(); Cool cool277 = factory277.getCool(); Video video277 = factory277.getVideo(); // 520型号产品族 Factory factory520 = new Factory520(); BMW bmw520 = factory520.getBmw(); Cool cool520 = factory520.getCool(); Video video520 = factory520.getVideo(); // 666型号产品族 Factory factory666 = new Factory666(); BMW bmw666 = factory666.getBmw(); Cool cool666 = factory666.getCool(); Video video666 = factory666.getVideo(); } }
此模式在framework中常用到,对于产品型号来说,扩展符合开闭原则,应为不需要修改源代码,直接继承扩展即可。但是对于产品族的扩展,却不符合开闭原则。若增加了新的配件,比如汽车加湿器,则需要在源代码中加入新的代码。
具体用哪个模式,参照实际设计中的业务场景,找到一款最符合的设计模式。