读书笔记:headfirst 设计模式 ,大话设计模式
简单工厂
简单工厂并不是一个设计模式,比较像一种编程习惯.
概念:将实例化具体类的代码抽离封装起来,使它们不会干扰应用的其他部分(松耦合),工厂类中,根据条件决定一个接口由哪个具体类来实现
代码案例
制造戴尔鼠标的工厂,
增加需求对惠普、华硕鼠标制造的支持(简单工厂,工厂方法),
增加需求对这三个厂商键盘的制造支持(抽象工厂)
public static void main(String[] args) {
// 不使用工厂直接创建戴尔鼠标
DellMouse newDellMouse = new DellMouse();
newDellMouse.sayName();
HpMouse newHpMouse = new HpMouse();
newHpMouse.sayName();
System.out.println("----------");
// 使用简单工厂创建 增加惠普鼠标
Mouse mouse = SimpleMouseFactory.createMouse(1);
mouse.sayName();
mouse = SimpleMouseFactory.createMouse(2);
mouse.sayName();
System.out.println("----------");
}
执行结果:
DellMouse
HpMouse
----------
HpMouse
DellMouse
----------
产品
public interface Mouse {
void sayName();
}
public class DellMouse implements Mouse {
@Override
public void sayName() {
System.out.println("DellMouse");
}
}
public class HpMouse implements Mouse {
@Override
public void sayName() {
System.out.println("HpMouse");
}
}
// 简单工厂
public class SimpleMouseFactory {
public static Mouse createMouse(int type) {
switch (type) {
case 1:
return new HpMouse();
case 2:
return new DellMouse();
}
return null;
}
}
代码结结构类图
这么做有什么好处?
- 工厂类可以有许多使用客户,当以后实现改变时,只需要修改这个工厂类即可.
- 客户代码绑定依赖具体类会导致代码缺乏弹性,要依赖抽象来松耦合
工厂方法模式
概念 : 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个工厂方法让类把实例化推迟到子类.
工厂方法模式结构图
代码案例
用工厂方法模式实现鼠标工厂案例
public static void main(String[] args) {
// 使用工厂方法 增加华硕鼠标
MouseFactory mouseFactory = new AsusMouseFactory();
Mouse asusMouse = mouseFactory.createMouse();
asusMouse.sayName();
// 切换惠普鼠标工厂
mouseFactory = new HpMouseFactory();
Mouse hpMouse = mouseFactory.createMouse();
hpMouse.sayName();
// 切换戴尔鼠标工厂
mouseFactory = new DellMouseFactory();
Mouse dellMouse = mouseFactory.createMouse();
dellMouse.sayName();
System.out.println("----------");
}
执行结果:
AsusMouse
HpMouse
DellMouse
----------
// 鼠标工厂接口
public interface MouseFactory {
Mouse createMouse();
}
// 华硕鼠标工厂
public class AsusMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new AsusMouse();
}
}
// 戴尔鼠标工厂
public class DellMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
// 惠普鼠标工厂
public class HpMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
}
工厂方法结构类图
简单工厂VS工厂方法
- 简单工厂类中聚集了所有实现过程的创建逻辑,如果要增加实现需要修改简单工厂类,违反开闭原则
- 工厂方法克服了简单工厂违背开闭原则的缺点(再添加一个工厂子类和实现类即可),又保持了封装对象创建过程的优点
- 如果实现过程逻辑比较复杂,将过程封装进工厂子类,别的地方可以复用
- 工厂方法适合配合参数配置与反射实现动态创建
依赖倒置(反转)原则 DI
要依赖抽象,不要依赖具体类
这个原则说明了:不能让高层组件依赖低层组件
帮助使用遵循原则
- 变量不可以持有具体类的引用
- 不要让类派生自具体类
- 不要覆盖基类中已实现的方法
抽象工厂模式
抽象工厂:对工厂方法进行扩展
概念 : 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
- 抽象工厂允许客户使用抽奖的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么
- 抽象工厂的每个方法实际上看起来都像是工厂方法
代码案例
用抽象工厂实现案例对鼠标,键盘产品族的支持
public static void main(String[] args) {
// 使用抽象工厂 ,扩展增加产品族 ,增加对键盘制造的支持
PcFactory pcFactory = new AsusPcFactory();
Keyboard asusKeyboard = pcFactory.createKeyboard();
asusKeyboard.sayName();
Mouse pcAsusMouse = pcFactory.createMouse();
pcAsusMouse.sayName();
// 切换惠普工厂
pcFactory = new HpPcFactory();
Keyboard hpKeyboard = pcFactory.createKeyboard();
hpKeyboard.sayName();
Mouse pcHpMouse = pcFactory.createMouse();
pcHpMouse.sayName();
// 切换戴尔工厂
pcFactory = new DellPcFactory();
Keyboard dellKeyboard = pcFactory.createKeyboard();
dellKeyboard.sayName();
Mouse pcDellMouse = pcFactory.createMouse();
pcDellMouse.sayName();
}
执行结果:
AsusKeyboard
AsusMouse
HpKeyboard
HpMouse
DellKeyboard
DellMouse
// 增加鼠标的同类产品族 -键盘
public interface Keyboard {
void sayName();
}
// 华硕键盘实现,戴尔惠普键盘略
public class AsusKeyboard implements Keyboard {
@Override
public void sayName() {
System.out.println("AsusKeyboard");
}
}
// 产品工厂接口抽象
public interface PcFactory {
Mouse createMouse();
Keyboard createKeyboard();
}
//华硕产品工厂
public class AsusPcFactory implements PcFactory {
@Override
public Mouse createMouse() {
return new AsusMouse();
}
@Override
public Keyboard createKeyboard() {
return new AsusKeyboard();
}
}
// 惠普产品工厂 戴尔产品工厂略
public class HpPcFactory implements PcFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
@Override
public Keyboard createKeyboard() {
return new HpKeyboard();
}
}
抽象工厂结构类图
抽象工厂与工厂方法比较
- 工厂方法通过类的继承创建对象,抽象工厂通过组合工厂方法创建对象
- 抽象工厂如果加入新产品需要改变接口
- 当需要创建产品家族和想让相关产品集合起来可以使用抽象工厂
- 把客户代码从需要实例化的具体类解耦或不知道将来要实例化哪些类时使用工厂方法
工厂模式要点
- 所有工厂都是用来封装对象的创建
- 所有工厂模式都是通过减少应用程序和具体类之间的依赖促进松耦合
- 简单工厂是一个可以将客户程序从具体类解耦的简单方法
- 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象
- 工厂方法允许类将实例化延迟到子类进行
- 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中
- 抽象工厂创建相关的对象家族,而不需要依赖他们的具体类
- 依赖倒置(反转)原则,指导我们避免依赖具体应该依赖抽象,针对抽象编程