设计模式之工厂模式
2020-01-31 本文已影响0人
sssssss_
模式定义
- 简单工厂模式:专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
-
工厂方法模式:定义一个用于
创建对象的接口
,让子类决定实例化
哪个类。 -
抽象工厂模式:定义一个
接口
用于创建相关或有依赖关系的对象族
,而无需明确
指定具体类。
模式使用场景
-
工厂方法模式:
- 复杂对象的生成,代替new的方式来屏蔽产品类的创建过程:需要一种产品,而不想知道也不需要知道工厂是如何生产出来的,只需要知道具体对应的工厂就行。
- 产品的替换需要灵活、可扩展性高的场合。
- Android中的Bitmap就是通过工厂方法来创建的。
-
抽象工厂模式:
- 一个对象族有相同的约束时可以使用抽象工厂模式,例如生成不同操作系统的程序。
简单工厂模式
简单工厂.jpgpublic abstract class Mouse {
public abstract void sayHi();
}
public class DellMouse extends Mouse {
@Override
public void sayHi() {
System.out.println("DellMouse - sayHi");
}
}
public class HpMouse extends Mouse {
@Override
public void sayHi() {
System.out.println("HpMouse - sayHi");
}
}
public class MouseFactory {
public Mouse createMouse(int i) {
switch (i) {
case 0:
return new DellMouse();
case 1:
return new HpMouse();
}
return null;
}
}
public class client {
public static void main(String[] args) {
MouseFactory mouseFactory = new MouseFactory();
Mouse m = mouseFactory.createMouse(0);
m.sayHi();
}
}
工厂模式
工厂模式.jpg// 省略 Mouse 、DellMouse、HpMouse 的代码
public abstract class MouseFactory {
public abstract Mouse createMouse();
}
public class DellMouseFactory extends MouseFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
public class HPMouseFarctrory extends MouseFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
}
public class client {
public static void main(String[] args) {
HPMouseFarctrory hpf = new HPMouseFarctrory();
Mouse mouse = hpf.createMouse();
mouse.sayHi();
}
}
抽象工厂模式
抽象工厂.jpg// 省略 Mouse 、DellMouse、HpMouse 的代码
public abstract class Keyboard {
public abstract void sayTara();
}
public class DellKeboard extends Keyboard {
@Override
public void sayTara() {
System.out.println("DellKeboard - sayTara");
}
}
public class HpKeyboard extends Keyboard {
@Override
public void sayTara() {
System.out.println("HpKeyboard - sayTara");
}
}
public abstract class PcFactory {
public abstract Mouse createMouse();
public abstract Keyboard createKeyboard();
}
public class DellFactory extends PcFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
@Override
public Keyboard createKeyboard() {
return new DellKeboard();
}
}
public class HpFactory extends PcFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
@Override
public Keyboard createKeyboard() {
return new HpKeyboard();
}
}
public class client {
public static void main(String[] args) {
HpFactory hp = new HpFactory();
Mouse mouse = hp.createMouse();
mouse.sayHi();
Keyboard k = hp.createKeyboard();
k.sayTara();
}
}
抽象工厂_产品结构增1.jpg在抽象工厂模式中,假设我们需要增加一个工厂
抽象工厂_产品族增1.jpg在抽象工厂模式中,假设我们需要增加一个产品
在抽象工厂模式中,采用
反射
的方式进行
public class client {
public static void main(String[] args) {
PcFactory factory = new ConcreteFactory();
Mouse m = factory.createMouse(DellMouse.class);
Keyboard k = factory.createKeyboard(DellKeboard.class);
m.sayHi();
k.sayTara();
}
}
public abstract class PcFactory {
public abstract <T extends Mouse> T createMouse(Class<T> mcls);
public abstract <K extends Keyboard> K createKeyboard(Class<K> kcls);
}
// 具体的工厂,动态传入
public class ConcreteFactory extends PcFactory {
@Override
public <T extends Mouse> T createMouse(Class<T> mcls) {
Mouse mouse = null;
try {
mouse = (Mouse) Class.forName(mcls.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) mouse;
}
@Override
public <K extends Keyboard> K createKeyboard(Class<K> kcls) {
Keyboard keyboard = null;
try {
keyboard = (Keyboard) Class.forName(kcls.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (K) keyboard;
}
}
依赖抽象原则:
- 变量不要持有具体类的引用;
- 不要让类继承自具体类,要继承自抽象类或接口;
- 不要覆盖基类中已实现的方法;
抽象工厂和工厂方法的区别
抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构
;而抽象工厂模式则需要面对多个产品等级结构
。
产品族和产品等级的概念
所谓产品族,是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。而这两个家族都来自于三个产品等级:主板、芯片组、CPU。一个等级结构是由相同的结构的产品组成。
产品族和产品等级模式优缺点
简单工厂模式:
- 优点1:使代码结构清晰;
- 优点2:对调用者屏蔽具体的产品类;
- 优点3:降低耦合度;
- 缺点1:当需求变动的时候,需要对原有的类进行修改,违背了开放封闭原则。
工厂方法模式:
- 优点1:加入新产品符合开闭原则,提高可扩展性;(接口)
- 缺点1:类的个数容易过多,增加复杂度;
- 缺点2:增加了系统的抽象性和理解难度;
抽象方法模式:
- 优点1:分离接口与实现;
- 优点2:在切换产品类时更灵活、容易;
- 缺点1:类文件的爆炸性增加;
- 缺点2:不太容易扩展新的产品类,因为增加一个产品类需要修改抽象工厂,那么所有的具体工厂均会被修改。(
所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
)
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦
。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
参考资料
- 《Android源码设计模式解析与实战》
- 抽象工厂UML:https://mp.weixin.qq.com/s/04JhViPnrfEWBopA28eYkw
- 抽象工厂图片:https://www.zhihu.com/question/20367734/answer/807965357
- 产品族的概念:https://www.jianshu.com/p/fd3455d48166