Java设计模式及应用场景之《抽象工厂模式》

一、抽象工厂模式定义

   抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
   在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

二、抽象工厂模式的结构和说明

在这里插入图片描述

  • AbstractFactory 抽象工厂,定义创建系列产品对象的操作接口。
  • ConcreteFactory 具体的工厂,实现抽象工厂定义的方法,具体实现系列产品对象的创建。
  • AbstractProduct 产品对象接口。
  • Product 实现产品对象接口的实现类。
三、应用抽象工厂模式来解决问题的思路

   创建一系列的产品对象,而且这一系列对象是构成新的对象所需要的组成部分,也就是这一系列被创建的对象相互之间是有关联的。
   解决这个问题的一个解决方案就是抽象工厂模式。在这个模式里,会定义一个抽象工厂,在里边虚拟的创建客户端需要的这一系列对象,所谓虚拟的就是定义创建这些对象的抽象方法,并不去真正的实现,然后由具体的抽象工厂的子类来提供这一系列对象的创建。这样一来,可以为同一个抽象工厂提供很多不同的实现,那么创建的这一系列对象也就不同了。

四、抽象工厂模式示例

  假设鼠标和键盘是我们需要的产品,生产鼠标和键盘的戴尔和联想是我们的工厂。

1、创建鼠标接口和具体的鼠标实现类

Mouse.java

/**
 * 鼠标接口
 */
public interface Mouse {

	/**
	 * 点击鼠标
	 */
	public void click();
}

DellMouse.java

/**
 * 戴尔鼠标
 */
public class DellMouse implements Mouse {

	@Override
	public void click() {
		System.out.println("使用戴尔鼠标进行点击...");
	}

}

LenovoMouse.java

/**
 * 联想鼠标
 */
public class LenovoMouse implements Mouse {

	@Override
	public void click() {
		System.out.println("使用联想鼠标进行点击...");
	}

}

2、创建键盘接口和具体的键盘实现类

Keyboard.java

/**
 * 键盘接口
 */
public interface Keyboard {

	/**
	 * 使用键盘打字
	 */
	public void type();
}

DellKeyboard.java

/**
 * 戴尔键盘
 */
public class DellKeyboard implements Keyboard {

	@Override
	public void type() {
		System.out.println("使用戴尔键盘打字...");
	}

}

LenovoKeyboard.java

/**
 * 联想键盘
 */
public class LenovoKeyboard implements Keyboard {

	@Override
	public void type() {
		System.out.println("使用联想键盘打字...");
	}

}

3、创建获取鼠标对象和键盘对象的抽象工厂

AbstractFactory.java

/**
 * 抽象工厂的接口,声明创建抽象产品对象的操作
 */
public interface AbstractFactory {
	
	/**
	 * 创建鼠标对象
	 * @return
	 */
	public Mouse createMouse();
	/**
	 * 创建键盘对象
	 * @return
	 */
	public Keyboard createKeyboard();
}

4、创建实现了抽象工厂的子工厂:戴尔工厂和联想工厂

DellFactory.java

/**
 * 戴尔工厂,生产戴尔鼠标和键盘
 */
public class DellFactory implements AbstractFactory {

	@Override
	public Mouse createMouse() {
		return new DellMouse();
	}

	@Override
	public Keyboard createKeyboard() {
		return new DellKeyboard();
	}

}

LenovoFactory.java

/**
 * 联想工厂,生产联想鼠标和键盘
 */
public class LenovoFactory implements AbstractFactory {

	@Override
	public Mouse createMouse() {
		return new LenovoMouse();
	}

	@Override
	public Keyboard createKeyboard() {
		return new LenovoKeyboard();
	}

}

5、在客户端用的时候,就可以这样用:

public class Client {

	public static void main(String[] args) {
		
		// 使用戴尔工厂
		AbstractFactory af = new DellFactory();
		
		Mouse m = af.createMouse();
		Keyboard kb = af.createKeyboard();
		
		m.click(); // 使用戴尔鼠标进行点击...
		kb.type(); // 使用戴尔键盘打字...
		
		
		// 更换为联想工厂
		af = new LenovoFactory();
		
		m = af.createMouse();
		kb = af.createKeyboard();
		
		m.click(); // 使用联想鼠标进行点击...
		kb.type(); // 使用联想键盘打字...
		
	}
}
五、抽象工厂模式的优缺点

优点:

  • 分离接口和实现。客户端面向产品的接口编程,从具体的产品实现中解耦。
  • 可以很方便的生产或切换产品系列。

缺点:

  • 不太容易扩展新产品。假如我们要给产品系列添加新的产品耳麦,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。
六、用反射机制+简单工厂模式改进代码

  我们将AbstractFactory、DellFactory以及LenovoFactory三个工厂类抛弃掉。取而代之的是一个简单工厂类SimpleFactory。

1、创建简单工厂

SimpleFactory.java

/**
 * 简单工厂,生产鼠标和键盘
 */
public class SimpleFactory {
	
	// 包名(此处getProperty方法为从配置文件中获取数据)
	private static String packName = getProperty("packName");
	// 具体需要的产品系列类型
	//(此处getProperty方法为从配置文件中获取数据)
    private static String type = getProperty("type");

    /**
     * 创建需要的鼠标对象
     * @return
     * @throws Exception
     */
	public static Mouse createMouse() throws Exception {
		
		String className = packName + "." + type + "Mouse";

        return (Mouse)Class.forName(className).newInstance();
	}

	/**
	 * 创建需要的键盘对象
	 * @return
	 * @throws Exception
	 */
	public static Keyboard createKeyboard() throws Exception{
		
		String className = packName + "." + type + "Keyboard";

        return (Keyboard)Class.forName(className).newInstance();
	}

}

2、配置文件中

packName=com.abstractfactory.example type=Dell

3、在客户端用的时候,就可以这样用:

public class Client {

	public static void main(String[] args) throws Exception {
		
		Mouse m = SimpleFactory.createMouse();
		Keyboard kb = SimpleFactory.createKeyboard();
		
		m.click(); // 使用戴尔鼠标进行点击...
		kb.type(); // 使用戴尔键盘打字...
		
	}
}

这样,如果我们需要更换产品系列,就可以不用修改和编译代码,直接修改配置文件就可以了。

七、抽象工厂模式的应用场景
  • 系统中有多于一个的产品族,而每次只使用其中某一产品族。
  • 在很多软件系统中需要更换界面主题或者一键换肤。
  • DAO层支持多种类型的数据库,动态切换时。
  • 不同操作系统代码差异化,可以切换不同操作系统时。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓呆同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值