工厂模式:创建对象的工厂
为什么要用工厂模式:
1,解耦
通过工厂模式可以把对象的创建和使用过程分离。
2,减少代码量,易于维护
如果我们直接new一个对象时,如果需要的对象构造方法比较复杂,那么可能需要一连串的代码去创建对象,如果在别的类中又需要创建该对象,那么代码的重复度肯定不小。通过工厂模式的话,我们把对象创建的具体逻辑给隐藏起来了,交给工厂统一管理,这样不仅减少了代码量,以后如果想改代码的话,只需要改一处即可,也方便我们日常的维护。
假如说,这个工厂现在用来生成蛋糕,下面先来看三个问题(弄懂这三个问题工厂模式翻篇)
1,任意定制蛋糕口味
2,任意定制蛋糕口味生产过程
3,任意定制生产蛋糕产品一族
一,我们先看第一个问题(任意定制蛋糕口味)
首先要有蛋糕的父类或者接口
package com.zl.factory; public interface Cake { void eat(); }
其次是具体的实现类
package com.zl.factory; //巧克力口味蛋糕 public class ChocolateCake implements Cake { @Override public void eat() { System.out.println("eat chocolateCake........"); } }
package com.zl.factory; //水果味蛋糕 public class FruitCake implements Cake { @Override public void eat() { System.out.println("eat fruitCake.........."); } }
最后就是运用到具体环境中,这里以测试类代替
package com.zl.factory; public class Test { public static void main(String[] args) { //定制水果味蛋糕 Cake cake = new FruitCake(); cake.eat(); } }
其实第一个问题就是Java多态
二,下面来第二个问题(任意定制蛋糕口味生产过程)
还是一样,先来几个具体的不同口味蛋糕
package com.zl.factory; //水果味蛋糕 public class FruitCake{ public void eat() { System.out.println("eat fruitCake.........."); } }
package com.zl.factory; //巧克力口味蛋糕 public class ChocolateCake { public void eat() { System.out.println("eat chocolateCake........"); } }
来一个蛋糕厂
package com.zl.factory; public class SimpleCakeFactory { public FruitCake createFruitCake(){ //before processing前置业务,如日志记录 return new FruitCake(); } public ChocolateCake createChocolateCake(){ //before processing前置业务,如日志记录 return new ChocolateCake(); } }
最后运用到具体环境中,还是以测试类代替
package com.zl.factory; public class Test { public static void main(String[] args) { //生产水果蛋糕 FruitCake fruitCake = new SimpleCakeFactory().createFruitCake(); fruitCake.eat(); //生产巧克力蛋糕 ChocolateCake chocolateCake = new SimpleCakeFactory().createChocolateCake(); chocolateCake.eat(); } }
这种也就是我们说的简单工厂,不过这种工厂比较混乱,什么蛋糕都生产,不专一
于是就有了我们说的工厂方法,为每一种口味蛋糕单一生产,废话少说,上代码
package com.zl.factory; public class FruitCakeFactory { public FruitCake create(){ //before processing前置业务,如日志记录 return new FruitCake(); } }
package com.zl.factory; public class ChocolateCakeFactory { public ChocolateCake create(){ //before processing前置业务,如日志记录 return new ChocolateCake(); } }
三,最后一个问题(任意定制生产蛋糕产品一族)
我们先来看一下传统的方法,假如我们要生产蛋糕,蛋糕蜡烛,蛋糕包装等蛋糕一族。
先来三个具体实现类
package com.zl.abstractFactory; //水果味蛋糕 public class FruitCake { public void eat() { System.out.println("eat fruitCake.........."); } }
package com.zl.abstractFactory; //红色蜡烛 public class RedCandle { public void see(){ System.out.println("it is red candle"); } }
package com.zl.abstractFactory; //简约的包装风格 public class SimpleStyle { public void style(){ System.out.println("it is simple..."); } }
具体客户端运用
package com.zl.abstractFactory; public class Test { public static void main(String[] args) { FruitCake cake = new FruitCake(); cake.eat(); RedCandle candle = new RedCandle(); candle.see(); SimpleStyle style = new SimpleStyle(); style.style(); } }
假如我们要换一个蛋糕套餐,要巧克力口味的,要蓝色的蜡烛和别的类型包装,上面的运用都要改
下面运用工厂进行改进
首先,先来抽象的产品,然后让具体的产品去继承即可(产品继承部分,代码省略)
package com.zl.abstractFactory; public abstract class Cake { abstract void eat(); }
package com.zl.abstractFactory; public abstract class Candle { public abstract void see(); }
package com.zl.abstractFactory; public abstract class Style { public abstract void style(); }
其次,用抽象的工厂生产抽象的产品
package com.zl.abstractFactory; public abstract class AbstractFactory { abstract Cake createCake(); abstract Candle createCandle(); abstract Style createStyle(); }
最后按照产品族去生产(继承abstractFactory),比如说生产(水果味,红色蜡烛,简约包装风格)这一族蛋糕,我们命名为FirstProductCake
package com.zl.abstractFactory; public class FirstProductCake extends AbstractFactory{ @Override Cake createCake() { return new FruitCake(); } @Override Candle createCandle() { return new RedCandle(); } @Override Style createStyle() { return new SimpleStyle(); } }
具体运用
package com.zl.abstractFactory; public class Test { public static void main(String[] args) { AbstractFactory factory = new FirstProductCake(); Cake cake = factory.createCake(); cake.eat(); Candle candle = factory.createCandle(); candle.see(); Style style = factory.createStyle(); style.style(); } }
当我们要不同的蛋糕套餐时,只需要去定义不同的生产族即可(继承abstractFactory)
这就是我们说的抽象工厂
可能到这里有些人有疑问,定义抽象产品直接用接口可以吗? 答案是可以的。这里就要抠语义了,蛋糕,蜡烛这些都是现实生活中存在的的东西,我们只是把它抽象出来,故用抽象类更适合。
比如说有个东西是“可移动的”,它可以是吃的东西,也可以是交通工具,也可以是动物,此时定义接口更合适。
(通俗一点,名词适合用抽象类,形容词适合用接口)
抽象工厂具体运用:比如我们开发了一款游戏,要为不同的英雄设计不同的皮肤,当我们更换英雄皮肤时,英雄外观会发生改变,英雄攻击会有相应的攻击特效,还有回城特效,这就相当于皮肤产品一族。
最后对比工厂方法和抽象工厂:
(1)工厂方法适合在产品维度上面去增加修改产品
(2)抽象工厂适合在产品族维度上面扩展产品套餐
(3)各有各的优势和不足
那有没有更完美的工厂,在这两个维度上面都可以扩展,答案,有。
那就是spring bean工厂,en。。。等读了源码在来分析......