【设计模式系列】--工厂方法

  1. 云栖社区>
  2. 博客>
  3. 正文

【设计模式系列】--工厂方法

丁国华 2016-09-25 17:20:52 浏览794
展开阅读全文

在前面的博文,小编介绍了简单工厂方法,今天我们继续来学习设计模式的知识。今天我们来学习一下工厂方法,那么什么是工厂方法呢?工厂方法在实际项目中又是如何应用的呢?工厂方法模式中包含的角色又具有什么样的职责呢?工厂方法和简单工厂模式之间又有着怎样千丝万缕的联系呢?今天这篇博文,小编就围绕这几个问题进行讲解,希望对有需要的小伙伴有帮助,不足之处,还请小伙伴多多指教。

什么是工厂方法模式

工厂方法模式属于类的创建型模式又称为多态工厂模式,工厂方法模式的意义是定义一个创建产品对象的工作接口,将实际创建工作推迟到子类当中,核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。我们来看一下工厂方法模式的类图,如下所示:


那我们如何使用工厂方法模式呢?以简单工厂模式的demo为例,把src中的全部类都复制粘贴到FactoryMethod工程当中,FruitFactory的代码如下所示:

public class FruitFactory {

	/**
	 * get方法,获得所有产品对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws ClassNotFoundException 
	 */
	public static Fruit getFruit(String type) throws InstantiationException, IllegalAccessException {
		if(type.equalsIgnoreCase("apple")) {
			return Apple.class.newInstance();
		}else if(type.equalsIgnoreCase("banana")){
			return Banana.class.newInstance();
		}else{
			System.out.println("找不到相关实例化类");
			return null;
			
		}
	
	}
	
}

MainClass的代码如下所示:

public class MainClass {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{

		Fruit apple = FruitFactory.getFruit("Apple");
		Fruit banana = FruitFactory.getFruit("Banana");
		apple.get();
		banana.get();
		
		
	}
}
这个时候我们需要添加一个新的水果呢?如何进行实现?新建类Pear并实现接口Fruit,代码如下所示:

public class Pear implements Fruit {

	@Override
	public void get() {
		System.out.println("采集梨子");

	}

}
如果我们想在MainClass里面获得一个梨子的对象,我们需要在FruitFactory中添加一个判断,代码如下所示:

public class FruitFactory {

	/**
	 * get方法,获得所有产品对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws ClassNotFoundException 
	 */
	public static Fruit getFruit(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		if(type.equalsIgnoreCase("apple")) {
			return Apple.class.newInstance();
		}else if(type.equalsIgnoreCase("banana")){
			return Banana.class.newInstance();
		}else if(type.equalsIgnoreCase("pear")){
			return Banana.class.newInstance();
		}else{
			System.out.println("找不到相关实例化类");
			return null;
			
		}
	
	}
	
}
编写MainClass里面的代码,如下所示:

public class MainClass {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{

		Fruit apple = FruitFactory.getFruit("Apple");
		Fruit banana = FruitFactory.getFruit("Banana");
		Fruit pear = FruitFactory.getFruit("Pear");
		apple.get();
		banana.get();
		pear.get();
		
	}
}
运行效果,运行如下所示:


这样的话,我们通过简单工厂可以实现,如果采用工厂方法该如何实现呢?简单工厂的缺点,我们添加一个产品,需要在FruitFactory里面添加判断,不符合开放封闭原则,工厂方法模式,不需要修改代码,工厂方法定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中,我们来看工厂方法如何实现:删除FruitFactory中的内容,重新编写,如下所示:

public interface FruitFactory{
	public Fruit getFruit();
}
如果要获得苹果,我们需要新建类AppleFactory并实现接口FruitFactory,编写相关代码如下所示:

public class AppleFactory implements FruitFactory {

	public Fruit getFruit(){
		return new Apple();
	}

}
如果要获得香蕉,我们需要新建类BananaFactory并实现接口FruitFactory,编写相关代码部分,如下所示:

public class BananaFactory implements FruitFactory {

	@Override
	public Fruit getFruit() {
		return new Banana();
	}

}
编写MainClass里面的代码,如下所示:

public class MainClass {

	public static void main(String[] args){
		//获得AppleFactory
		FruitFactory ff = new AppleFactory();
		//通过AppleFactory来获得Apple实例对象
		Fruit apple = ff.getFruit();
		apple.get();
		
		//获得BananaFactory
		FruitFactory ff2 = new BananaFactory();
		//通过BananaFactory来获得Banana实例对象
		Fruit banana = ff2.getFruit();
		banana.get();
	}
}
执行,如下所示:


所以,这样的好处在哪儿呢?新添加了一个pear,不需要修改FruitFactory,不需要修改BananaFactory和AppleFactory,我们需要做的是新家类PearFactory类并实现接口FruitFactory,编写相关的代码部分,如下所示:

public class PearFactory implements FruitFactory {

	@Override
	public Fruit getFruit() {
		return new Pear();
	}

}
编写MainClass类,代码如下所示:

public class MainClass {

	public static void main(String[] args){
		//获得AppleFactory
		FruitFactory ff = new AppleFactory();
		//通过AppleFactory来获得Apple实例对象
		Fruit apple = ff.getFruit();
		apple.get();
		
		//获得BananaFactory
		FruitFactory ff2 = new BananaFactory();
		//通过BananaFactory来获得Banana实例对象
		Fruit banana = ff2.getFruit();
		banana.get();
		
		//获得PearFactory
		FruitFactory ff3 = new PearFactory();
		//通过PearFactory来获得Banana实例对象
		Fruit pear= ff3.getFruit();
		pear.get();
	}
}
运行,效果如下所示:


这样是完全符合开放封闭原则的,我们添加一个新的pear,我们不需要修改其她的工程,直接新建就可以,结合上面的类图,我们来看一下模式中包含的各种角色以及职责。

a、抽象工厂(Creator)角色

工厂方法模式的核心,任何工厂类都必须实现这个接口。

b、具体工厂(ConcreteCreator)角色

具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

c、抽象(Product)角色

工厂方法模式所创建的所有对象的父类,她负责描述所有实例所共有的公共接口。

d、具体产品(ConcreteProduct)角色

工厂方法模式所创建的具体实例对象

接着,我们来比较一下工厂方法模式和简单工厂模式,如下所示:

a、工厂方法模式与简单工厂模式在结构上的不同不是很明显,工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
b、工厂模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者共同的抽象父类。
c、当系统扩展需要添加新的产品对象的时候,仅仅需要添加一个具体对象以及具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了开放-封闭原则,而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
d、工厂方法模式退化后可以演变成简单工厂模式。

小编寄语:该博文,小编主要简单的介绍了工厂方法模式,通过一个简单的demo进行讲解,简单工厂模式是属于创建型模式,工厂方法模式属于类的创建型模式又称为多态工厂模式,工厂方法模式的意义是定义一个创建产品对象的工作接口,将实际创建工作推迟到子类当中,核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品编程是一门技术,更是一门艺术,在编写代码的过程中,要牢记可复用、易维护、好扩展,这样,自己才能有所提高,才是真正的软件工程师。

网友评论

登录后评论
0/500
评论
丁国华
+ 关注