1. 简单工厂模式
简单工厂模式是指有一个工厂对象决定创建出哪一个产品类的实例;属于创建型模式
,但它不属于GOF 23种设计模式。
UML类图
组成要素
1、一个抽象产品类
2、具体产品类
3、一个工厂
肥宅喜爱的各种快乐水(产品接口)
1 2 3
| public interface Kls { String name(); }
|
肥宅快乐水-可乐(具体产品)
1 2 3 4 5 6
| public class Coke implements Kls { @Override public String name() { return "肥宅快乐水-可乐"; } }
|
快乐水-雪碧(具体产品)
1 2 3 4 5 6
| public class Sprite implements Kls { @Override public String name() { return "快乐水-雪碧"; } }
|
快乐水生产工厂(工厂类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class KlsFactory { public static Kls getFzs(String type) throws Exception { Kls fzs = null; if ("coke".equalsIgnoreCase(type)) { fzs = new Coke(); } else if ("sprite".equalsIgnoreCase(type)) { fzs = new Sprite(); } if (Objects.isNull(fzs)) { throw new RuntimeException("没找到快乐水~"); } return fzs; } }
|
客户端使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Fz { @Test public void drink() throws Exception { Kls coke = KlsFactory.getFzs("coke"); System.out.println("肥宅开始喝:" + coke.name());
Kls sprite = KlsFactory.getFzs("sprite"); System.out.println("肥宅开始喝:" + sprite.name()); } }
|
1.1 优点
- 对客户端隐藏的具体的实现,客户端只需要知道要创建什么对象即可,不用关心对象是怎么创建的
- 解耦,客户端不需要通过new来创建对象,如果后期产品类需要修改,则只需要修改工厂类即可,不用整个项目遍地去寻找哪里有new
1.2 缺点
- 由一个专门的工厂负责生产,如果业务变得复杂,这个类将变得十分臃肿
- 工厂类生产什么产品都是写死在工厂中的,如果增加新的产品,还要修改工厂类的生产逻辑
2. 工厂方法模式
工厂方法模式(Factory Method)是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
组成要素
1、一个抽象产品类
2、多个具体产品类
3、一个抽象工厂
4、多个具体工厂 - 每一个具体产品对应一个具体工厂
5、符合 - OCP开放封闭原则
接着上面快乐水的例子。将 快乐水工厂 (KlsFactory) 抽象出共有方法,再分别实现具体的快乐水生产工厂。
快乐水总工厂
1 2 3 4 5 6 7 8
| public interface Factory {
Kls create(); }
|
可乐工厂
1 2 3 4 5 6
| public class CokeFactory implements Factory { @Override public Kls create() { return new Coke(); } }
|
雪碧工厂
1 2 3 4 5 6
| public class SpriteFactory implements Factory { @Override public Kls create() { return new Sprite(); } }
|
肥宅(客户端)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Fz { @Test public void drink() throws Exception { CokeFactory cokeFactory = new CokeFactory(); Kls coke = cokeFactory.create(); System.out.println("肥宅开始喝:" + coke.name());
SpriteFactory spriteFactory = new SpriteFactory(); Kls sprite = spriteFactory.create(); System.out.println("肥宅开始喝:" + sprite.name()); } }
|
扩展芬达快乐水
1 2 3 4 5 6
| public class Fanta implements Kls { @Override public String name() { return "快乐水-芬达"; } }
|
复制代码芬达工厂
1 2 3 4 5 6
| public class FantaFactory implements Factory { @Override public Kls create() { return new Fanta(); } }
|
肥宅使用添加
1 2 3
| FantaFactory fantaFactory = new FantaFactory(); Kls fanta = fantaFactory.create(); System.out.println("肥宅开始喝:" + fanta.name());
|
2.1 优点
1、降低了代码耦合度,对象的生成交给子类去完成(这里的耦合度是相对于简单工厂模式的工厂类比较的)
2、降低了代码耦合度,对象的生成交给子类去完成
2.2 缺点
1、增加了代码量,每个具体产品都需要一个具体工厂(在具体的业务中可能会产生大量的重复代码)
2、当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP
3. 抽象工厂模式
组成要素
1、多个抽象产品类
2、具体产品类
3、抽象工厂类 - 声明(一组)返回抽象产品的方法
4、具体工厂类 - 生成(一组)具体产品
一个抽象产品类和两个具体的产品(可乐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public abstract class Coke { public abstract void doCreate(); }
public class LocalCoke extends Coke{ @Override public void doCreate() { System.err.println("生产本土可乐"); } }
public class ForeignCoke extends Coke{ @Override public void doCreate() { System.out.println("生产外国可乐"); } }
|
一个抽象产品类和两个具体的产品(雪碧)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public abstract class Sprite { public abstract void doCreate(); }
public class LocalSprite extends Sprite{ @Override public void doCreate() { System.out.println("生产本地雪碧"); } }
public class ForeignSprite extends Sprite{ @Override public void doCreate() { System.err.println("生产外国雪碧"); } }
|
一个抽象工厂和两个具体的工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public interface IAbstractFactory {
Coke createCoke();
Sprite createSprite(); }
public class LocalFactory implements IAbstractFactory{
@Override public LocalCoke createCoke() { return new LocalCoke(); }
@Override public LocalSprite createSprite() { return new LocalSprite(); } }
public class ForeignFactory implements IAbstractFactory{
@Override public ForeignCoke createCoke() { return new ForeignCoke(); }
@Override public ForeignSprite createSprite() { return new ForeignSprite(); } }
|
3.1 抽象工厂的使用
1 2 3 4 5 6 7 8 9 10 11
| public class FactoryTest { public static void main(String[] args) { LocalFactory localFactory = new LocalFactory(); LocalCoke localCoke = localFactory.createCoke(); localCoke.doCreate();
ForeignFactory foreignFactory = new ForeignFactory(); ForeignSprite foreignSprite = foreignFactory.createSprite(); foreignSprite.doCreate(); } }
|
3.2 优点
1、代码解耦
2、很好的满足OCP开放封闭原则
3、抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产相当灵活易扩展
(相对于工厂方法模式的优化)
3.3 缺点
1、扩展产品是需要修改所有工厂,违反违反OCP原则
2、整体实现也比较复杂
参考文章
还有多少个十年 继续做热血少年