设计模式之工厂模式

设计模式之工厂模式

工厂模式分为简单工厂模式,工厂方法模式,抽象工厂方法模式三种,但是其中简单工厂方法其实不在23中设计模式之中,都属于创建型的设计模式。

简单工厂模式

简单工厂方法其实不属于工厂模式的,他只是一种设计思想,是一种对接口的编程的习惯。简单工厂抽象出一个公共的接口,不同的对象实现这个公共的接口。最后定义一个工厂类,根据不同的条件来返回不同类型的实例.

简单工厂的使用场景

  1. 创建对象类型相同,但实现不同,最重要的一点就是创建对象的类型数目较小
  2. 创建过程,对象细节实现客户端不关心

举个简单的例子,就拿在游戏中准备武器材料合成武器这个场景来展开,我需要刀、剑、斧等武器。我需要准备武器的材料和具体的设计图,交给武器制造者。具体怎么打造武器,我并不用关心,最后有一个成果出来就没问题。

这里的制造者就是一个工厂,根据一个设计图就能够制造很多相同的武器。不同的设计图制造不同的武器类型。理解这个,来看简单工厂的组成结构。

简单工厂结构

简单工厂可以分为大致三个部分:

  1. 抽象产品接口,定义产品公共方法,比如武器的攻击方式
  2. 产品接口实现类,实现产品接口中的方法,给出具体行为,比如刀就是砍,剑就是刺
  3. 工厂类,制造出具体产品,比如工匠依据图纸打造具体的武器

%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F%20dc400f3d7f7e48dc9bff810a46308fd6/Untitled.png

代码

武器接口和武器实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Weapon {
public String attack();
}
public class Sword implements Weapon{
@Override
public String attack() {
System.out.println("使用刀用来砍向敌人!!");
return "攻击方式: 砍";
}
}
public class Axe implements Weapon{
@Override
public String attack() {
System.out.println("使用斧子用来劈向敌人!!");
return "攻击方式: 劈";
}
}

工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class WeaponFactory {

public static Weapon build(WeaponType weaponType){
if(WeaponType.AXE.equals(weaponType)){
return new Axe();
}else if(WeaponType.SWORD.equals(weaponType)){
return new Sword();
}
return null;
}
}
// 枚举武器类型
public enum WeaponType {
SWORD,AXE
}

客户端测试

1
2
3
4
5
6
7
8
9
10
public class Gamer {
public static void main(String[] args) {
// 使用工厂制造一个斧子
Weapon axe = WeaponFactory.build(WeaponType.AXE);
axe.attack();
// 使用工厂制造一个刀
Weapon sword = WeaponFactory.build(WeaponType.SWORD);
sword.attack();
}
}

上面举的一个小栗子,主要想体现两点

  • 客户端不再自己创建具体事例,而是根据特定类型要求工厂创建
  • 相同的行为封装接口的编程习惯

工厂方法模式

通过查看前面的简单工厂代码可以发现,在工厂内是通过if..else结构进行判断需要创建哪个类型的武器,工厂方法模式可以通过抽象工厂,创建一个公共的工厂接口类,通过实现类去实现结构,在调用的时候通过使用实现类来实例化特定的工厂。也就是说,工厂方法类同样需要通过子类去实例化建造对象.

工厂方法的应用场景

  1. 和简单工厂相同,创建对象类型相同,但实现不同
  2. 和简单工厂不同的是,工厂方法模式不再让客户端面对对象类型,而是面对工厂类型,并且可以通过工厂指定不同的属性的对象,可以看下面的实例。

还是在打造武器的例子的基础上,但是现在制造者进行了分门别派,有专门制造斧子的制造者,有专门制造刀的制造者。

  • 在原来,需要对制造者说:”给我来一把斧子!“,那么制造者会拿起斧子的制造模板,开始制造
  • 在现在,只需要走到专门制造斧子的制造者前面,对制造者说:”给我来把武器/附魔的武器“,那么制造者自然会给你一把对应的斧子。

工厂方法结构

工厂方法大致分为四个部分:

  1. 抽象产品接口,定义公共产品方法,如下图的weapon方法
  2. 产品实现类和特殊属性实现类,如下图中的Axe和EnchanteAxe
  3. 抽象工厂,定义生产产品接口
  4. 工厂实现类,实现具体的生产方法工厂方法模

%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F%20dc400f3d7f7e48dc9bff810a46308fd6/Untitled%201.png

代码

  • 抽象产品和产品实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Weapon {
public String attack();
}
public class Axe implements Weapon {
@Override
public String attack() {
System.out.println("使用斧子用来劈向敌人!!");
return "攻击方式: 劈";
}
}
public class EnchantedAxe extends Axe{

@Override
public String attack() {
System.out.println("使用一把附魔的斧子用来劈向敌人!!");
return "攻击方式: 劈";
}
}
  • 抽象工厂和工厂实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface WeaponFactory {
public Weapon build(boolean isEnchanted);
}
public class AxeFactory implements WeaponFactory {

@Override
public Weapon build(boolean isEnchanted) {
// 如果是需要附魔的武器,则返回 附魔的斧子
// 否则返回正常的斧子
if(isEnchanted){
return new EnchantedAxe();
}else{
return new Axe();
}
}
}
  • 客户端调用
1
2
3
4
5
6
7
8
9
10
11
public class Gamer {
public static void main(String[] args) {
// 声明一个工厂
WeaponFactory axeFactory = new AxeFactory();
// 创建一个附魔的斧子
Weapon enchantedAxe = axeFactory.build(true);
enchantedAxe.attack();
Weapon axe = axeFactory.build(false);
axe.attack();
}
}

抽象工厂模式

提供用于创建相关或从属的对象族(多个组件,并且组件之间是由必要联系的)的接口,而无需指定其具体类.是对工厂方法的再次延展。需要注意的是,这里的相关或从属的对象组指的是相关联的一系列的对象。

如在游戏时,不光需要武器,还要需要防具,这时的武器和防具就属于”一个对象族“,他们相关联,需要同时创建。

抽象工厂应用场景

抽象工厂方法是工厂方法的进阶,是对工厂方法中的生成的对象的再次包装。

抽象方法结构

抽象方法结构可以分为四部分:

  1. 分离的产品组件接口
  2. 产品组件实现接口
  3. 抽象工厂接口。声明一组方法,用来创建一组对象
  4. 具体工厂。针对抽象工厂接口中的创建方法,进行具体实现

%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F%20dc400f3d7f7e48dc9bff810a46308fd6/Untitled%202.png

实现代码

  • 产品组件,分别定义了接口和相对应的实现
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
public interface Weapon {
public String attack();
}
public interface Armor {
String defence();
}

public class Axe implements Weapon {
@Override
public String attack() {
System.out.println("使用斧子用来劈向敌人!!");
return "攻击方式: 劈";
}
}
public class EnchantedAxe extends Axe {
@Override
public String attack() {
System.out.println("使用一把附魔的斧子用来劈向敌人!!");
return "攻击方式: 劈";
}
}
public class IronArmor implements Armor{
@Override
public String defence() {
System.out.println("使用铁制防具防御");
return "铁质防具";
}
}
public class SteelArmor implements Armor {
@Override
public String defence() {
System.out.println("使用精钢制防具防御");
return "精钢质防具";
}
}
  • 工厂接口和实现,不同类型的工厂制造不同的一组组件
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
public interface WarFactory {
public Weapon buildWeapon();
public Armor buildArmor();
}
public class LowerFactory implements WarFactory{
// 低级的制造工厂
@Override
public Weapon buildWeapon() {
return new Axe();
}

@Override
public Armor buildArmor() {
return new IronArmor();
}
}
public class SeniorFactory implements WarFactory {
@Override
public Weapon buildWeapon() {
return new EnchantedAxe();
}

@Override
public Armor buildArmor() {
return new SteelArmor();
}
}
  • 客户端实现
1
2
3
4
5
6
7
8
9
10
public class Gamer {

public static void main(String[] args) {
WarFactory senior = new SeniorFactory();
Armor armor = senior.buildArmor();
armor.defence();
Weapon weapon = senior.buildWeapon();
weapon.attack();
}
}

可以看到,抽象工厂模式中,如果还需定义更多的组件,那么需要在每个抽象工厂和实现工厂中添加对应方法,这样不满足开闭原则,所以在实际应用中局限性很大。

-------------本文结束感谢您的阅读-------------

本文标题:设计模式之工厂模式

文章作者:NanYin

发布时间:2019年05月29日 - 12:05

最后更新:2023年07月30日 - 17:07

原始链接:https://nanyiniu.github.io/2019/05/29/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。