首页 > 代码库 > 工厂模式
工厂模式
先说下我对工厂模式的理解:当我们需要某个对象时,最直接的办法是看到这个对象就拿过来。但是当对象非常多的时候,找起来就很不方便。这时就需要一个中介来帮助我们取得想要的东西,这个中介就是工厂(factory)。
工厂模式可分为三个分类(简单工厂模式Simple Factory、 工厂方法模式Factory Method、 抽象工厂模式Abstract Factory)
我来模拟一个场景:动物园管理员每天都要确保动物的健康,确定动物健康的一种简单方法就是听一听动物的叫声是不是正常。这样,管理员就需要随时找到任一种动物以确定动物的情况。下面是动物相关类(至于动物园为什么有猫和狗大家就不要太计较了……):
interface:Animal(动物的接口)
package com.captain.factory;/** * <P>Title:动物接口<p> * @author 船长工作室 */public interface Animal { void call();}
package com.captain.factory;/** * <p>Title:猫<p> * @author 船长工作室 */public class Cat implements Animal { /** * 猫叫 * @param 无 * @return void */ public void call() { System.out.print("meow"); }}package com.captain.factory;/** * <p>Title:狗<p> * @author 船长工作室 */public class Dog implements Animal { /** * 狗叫 * @param 无 * @return void */ public void call() { System.out.print("bark"); }}package com.captain.factory;/** * <p>Title:老虎<p> * @author 船长工作室 */public class Tiger implements Animal { /** * 老虎叫 * @param 无 * @return void */ public void call() { System.out.print("roar"); }}
下面先介绍简单工厂模式:
class:SimpleFactory(简单工厂)
package com.captain.factory;/** * <p>Title:简单工厂模式-工厂类<p> * @author 船长工作室 */public class SimpleFactory { /** * 召唤动物 * @param s 召唤动物的种类 * @return animal 该种类的动物实例 */ public static Animal search(String s){ Animal animal = null; if ("cat".equals(s)){//判断召唤动物的种类 animal = new Cat(); }else if("dog".equals(s)){ animal = new Dog(); }else if("tiger".equals(s)){ animal = new Tiger(); } return animal;//返回找到的动物 }}package com.captain.factory;/** * <p>Title:简单工厂模式-动物管理员<p> * @author 船长工作室 */public class SimpleManager { /** * 动物管理员找到所需动物,并让该动物叫出声来 * @param args */ public static void main(String[] args) { Animal animal = SimpleFactory.search("dog");//从工厂中获得指定类型动物 if ( animal == null ){ System.out.print("can‘t find this kind of animal!"); return;//没有找到指定动物,返回 } animal.call();//让得到的动物叫出声来 }}
简单工厂通过一个工厂对象来管理、查询各个对象。比较简单、方便。但是当添加新的动物时,我们不仅要添加新的动物类,还要修改工厂中的逻辑(if()...else if()...else if()...)。当逻辑比较复杂时,就会很混乱……
工厂方法模式就解决了这个问题:
Interface:CallAnimal(召唤动物)
package com.captain.factory;/** * <p>Title:召唤动物接口<p> * @author 船长工作室 */public interface CallAnimal { /** * 得到召唤的动物 * @return Animal 召唤的动物 */ Animal callAnimal();}package com.captain.factory;/** * <p>Title:得到猫<p> * @author 船长工作室 */public class CallCat implements CallAnimal { /** * 得到猫 * @return Cat 猫 */ public Animal callAnimal() { return new Cat(); }}package com.captain.factory;/** * <p>Title:得到狗<p> * @author 船长工作室 */public class CallDog implements CallAnimal { /** * 得到狗 * @return Dog 狗 */ public Animal callAnimal() { return new Dog(); }}package com.captain.factory;/** * <p>Title:得到老虎<p> * @author 船长工作室 */public class CallTiger implements CallAnimal { /** * 得到老虎 * @return Tiger 老虎 */ public Animal callAnimal() { return new Tiger(); }}package com.captain.factory;/** * <p>Title:工厂方法模式-动物管理员<p> * @author 船长工作室 */public class MethodManager { /** * 动物管理员通过指定工厂找到所需动物,并让该动物叫出声来 * @param args */ public static void main(String[] args){ CallAnimal callAni = new CallCat();//调用指定动物工厂 Animal animal = callAni.callAnimal();//获得指定 animal.call();//让动物叫 }}
工厂方法模式通过一个工厂一个对象的形式,解决了上述问题。当需要一个新的对象时,只需新建一个对应的工厂,并在使用时调用相应的工厂就好了。但是这种方式会随着对象的增加而出项很多很多的工厂对象……
下面介绍抽象工厂模式:
我认为抽象工厂模式适用于有分类的情况。比如HP、DELL、Lenov都有台式机和笔记本、智能手机出售。这时可以为每个品牌建立一个工厂,工厂里得到该品牌的产品(台式机、笔记本、智能手机)。想买什么产品,将调用相应品牌的对应方法,得到该产品。
还以我们的动物园管理员举例。现在我们的管理员需要对动物按性别进行管理。这样,我们就需要建立雄性和雌性两个接口。
Interface:Male(雄性)
package com.captain.factory;/** * <p>Title:雄性<p> * @author 船长工作室 */public interface Male {}package com.captain.factory;/** * <p>Title:雌性<p> * @author 船长工作室 */public interface Female {}package com.captain.factory;/** * <p>Title:公猫<p> * @author 船长工作室 */public class MaleCat extends Cat implements Male{ /** * 公猫叫 * @param 无 * @return void */ public void call() { System.out.print("male-meow"); }}package com.captain.factory;/** * <p>Title:公狗<p> * @author 船长工作室 */public class MaleDog extends Dog implements Male{ /** * 公狗叫 * @param 无 * @return void */ public void call() { System.out.print("male-bark"); }}package com.captain.factory;/** * <p>Title:公老虎<p> * @author 船长工作室 */public class MaleTiger extends Tiger implements Male{ /** * 公老虎叫 * @param 无 * @return void */ public void call() { System.out.print("male-roar"); }}package com.captain.factory;/** * <p>Title:母猫<p> * @author 船长工作室 */public class FemaleCat extends Cat implements Female{ /** * 母猫叫 * @param 无 * @return void */ public void call() { System.out.print("female-meow"); }}package com.captain.factory;/** * <p>Title:母狗<p> * @author 船长工作室 */public class FemaleDog extends Dog implements Female{ /** * 母狗叫 * @param 无 * @return void */ public void call() { System.out.print("female-bark"); }}package com.captain.factory;/** * <p>Title:母老虎<p> * @author 船长工作室 */public class FemaleTiger extends Tiger implements Female{ /** * 母老虎叫 * @param 无 * @return void */ public void call() { System.out.print("female-roar"); }}
分类完毕之后,我们需要定义一个工厂接口,这个接口能够获得所有种类的对象(比如猫、狗、老虎)
Interface:AbstractFactory(抽象工厂)
package com.captain.factory;/** * <p>Title:抽象工厂<p> * @author 船长工作室 */public interface AbstractFactory { /** * 获得猫 * @return 猫 */ Cat callCat(); /** * 获得狗 * @return 狗 */ Dog callDog(); /** * 获得老虎 * @return 老虎 */ Tiger callTiger();}有了接口,我们要实现两个具体工厂(分别是公的和母的……)class:MaleFactory(雄性工厂)package com.captain.factory;/** * 获得雄性动物 * @author 船长工作室 */public class MaleFactory implements AbstractFactory { /** * 获得公猫 * @return 公猫 */ public Cat callCat() { return new MaleCat(); } /** * 获得公狗 * @return 公狗 */ public Dog callDog() { return new MaleDog(); } /** * 获得公老虎 * @return 公老虎 */ public Tiger callTiger() { return new MaleTiger(); }}class:FemaleFactory(雌性工厂)package com.captain.factory;/** * 获得雌性动物 * @author 船长工作室 */public class FemaleFactory implements AbstractFactory { /** * 获得母猫 * @return 母猫 */ public Cat callCat() { return new FemaleCat(); } /** * 获得母狗 * @return 母狗 */ public Dog callDog() { return new FemaleDog(); } /** * 获得母老虎 * @return 母老虎 */ public Tiger callTiger() { return new FemaleTiger(); }}有了以上两个工厂,我们就可以获得其中一种性别的动物了class:AbstractManager(动物园管理员)package com.captain.factory;/** * <p>Title:抽象工厂模式-动物管理员<p> * @author 船长工作室 */public class AbstractManager { /** * 动物管理员找到所需动物,并让该动物叫出声来 * @param args */ public static void main(String[] args) { FemaleFactory maleFac = new FemaleFactory();//建立雌性动物工厂 Animal animal = maleFac.callTiger();//从工厂中获得指定类型动物 if ( animal == null ){ System.out.print("can‘t find this kind of animal!"); return;//没有找到指定动物,返回 } animal.call();//让得到的动物叫出声来 }}
可见,管理员通过建立雌性动物工厂,得到了母老虎……
采用抽象工厂时,有几个分类就有几个工厂(HP、DELL、Lenovo等),每个工厂里,有几种产品就有几个方法(createDesktop、createNotebook、createPhone等)。
工厂模式