Java设计模式(3)之工厂方法模式&抽象工厂模式学习总结

工厂模式&抽象工厂模式

工厂模式主要用于实现将对象的实例化部分取出来,进而优化系统架构,增强系统的扩展性。

工厂模式的适用场景:

1. 需要创建一组类似的对象,对应于需要生产一个产品族的不同产品;
2. 在编写代码时,不能预见需要创建哪种类的实例,即不能预见需要生产哪种产品;指定的类型由客户端的具体要求决定,从而实现功能的剥离;
3. 需要考虑系统的扩展性,系统的实现不能依赖于产品类实例如何被创建、组合及表达的细节;

工厂模式的作用:

使用工厂提供的方法代替new操作进行实例的获取;    

工厂模式的目的:

①尽量使设计达到松耦合,即对象的变化不会影响到依赖于该对象的对象的变化,这也是为什么使用接口进行工厂模式设计的原因之一;
②剥离具体产品的生产与客户端,实现责任分割;即由客户端指定需要生产的具体产品,由工厂进行该产品的生产;

工厂模式的分类:

工厂方法模式和抽象工厂模式;  

工厂模式和抽象工厂模式是在日常开发中使用非常广泛的设计模式。

两者的联系:

①工厂方法模式可以视为抽象工厂模式的一种特例;抽象工厂模式是工厂方法模式的扩展;
②工厂方法模式一般针对一个产品族的产品生产进行设计;抽象工厂模式一般针对多个产品族的产品的生产进行设计;

相关关键词:工厂类、产品族、系列

工厂模式的设计思路:

①定义一个稳定的公共接口作为产品族中的不同产品类的实现接口(产品族接口),把具体产品的实例化,放到工厂方法中进行实现;
②分别进行不同的产品类的设计,必须实现产品族接口;
③定义一个产品族的工厂类,该类主要提供获取不同种类产品的方法(工厂方法);
注意:
①这里的工厂方法的设计要尽可能地通用化,一般设计为只需要提供一个关键词就可以获取一个产品的工厂方法;
②这里的工厂方法可以使用反射机制进行设计,根据指定的产品类的类名进行对象的实例化;
为避免类名过长,可以通过映射简化类名,在properties文件中,进行关键词和类名的映射;

设计案例:

以最近比较火的手游王者荣耀作为例子,其中的英雄属于一个产品族,这个产品族中包含坦克类英雄、射手类英雄以及辅助类英雄等;
这里将英雄设计为一个接口HeroInterface;不同的英雄类通过实现该接口进行设计,生产不同类型英雄的工厂类提供工厂方法进行英雄的生产;
    package design.pattern.hero;
    //英雄类公共接口
    public interface HeroInterface
    {
        public HeroInterface produce();
    }

    package design.pattern.hero;
    //坦克英雄类
    public class TankHero implements HeroInterface
    {
        @Override
        public HeroInterface produce()
        {
            System.out.println("坦克型英雄");
            //return new TankHero();
        }

    package design.pattern.hero;
    //法师英雄类
    public class MasterHero implements HeroInterface
    {
        @Override
        public HeroInterface produce()
        {
            System.out.println("法师型英雄");
            //return new MasterHero();
        }

    package design.pattern.hero;
    //辅助英雄类
    public class AuxiliaryHero implements HeroInterface
    {
        @Override
        public HeroInterface produce()
        {
            System.out.println("辅助型英雄");
            //return new AuxiliaryHero();
        }
    }

    package design.pattern.hero;
    //生产英雄的工厂类
    public class HeroFactory
    {
        //方法一:通过类型获取对应的英雄
        public static HeroInterface produceHeroByType(String type)
        {
            if("Tank".equals(type))
            {
                return new TankHero().produce();
            }else if("Master".equals(type))
            {
                return new MasterHero().produce();
            }else if("Auxiliary".equals(type))
            {
                return new AuxiliaryHero().produce();
            }
            return null;
        }

        //方法二:通过类名获取相应类的英雄
        public static HeroInterface produceHeroByClassName(String className)
        {
            try {
            HeroInterface hero = (HeroInterface) Class.forName(className).newInstance();
            return hero.produce();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
        }

        //方法三:通过类名对应的关键字获取相应类的英雄
        public static HeroInterface produceHeroByClassKey(String key)
        {
            try {
            Map<String, String> map = new PropertiesReader().getProperties();
            HeroInterface hero = (HeroInterface) Class.forName(map.get(key)).newInstance();
            return hero.produce();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
        }

    }

    package design.pattern.hero;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;

    /**
     * properties文件的读取工具
     * @author Administrator
     *
     */
    public class PropertiesReader {
        public Map<String, String> getProperties() {
            Properties props = new Properties();
            Map<String, String> map = new HashMap<String, String>();
            try {
                InputStream in = getClass().getResourceAsStream("type.properties");
                props.load(in);
                Enumeration en = props.propertyNames();
                while (en.hasMoreElements()) {
                    String key = (String) en.nextElement();
                    String property = props.getProperty(key);
                    map.put(key, property);
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }
}
design.pattern.hero包下的type.properties文件:
Tank=design.pattern.hero.TankHero
Master=design.pattern.hero.MasterHero
Auxiliary=design.pattern.hero.AuxiliaryHero

抽象工厂模式的设计思路:

抽象工厂模式一般适用于需要生产多个产品族的产品的场景;这里以最简单的(两个产品族)作为例子讲解:
产品族A和产品族B  系列X和系列Y
①分别设计对应于产品族A、B的产品族接口;
②根据系列的不同,将产品族A、B的产品类实现为不同系列下的产品类;
③设计一个包含获取产品族A、B的产品的方法的公共接口(产品族公共接口);
④基于实现产品族公共接口,进行不同系列下的工厂类的设计;
这里的工厂类依据不同的系列,分为两个工厂类(系列X、Y的工厂类);
系列X的工厂类的工厂方法用于生产系列X下的产品族A和产品族B的产品;
系列Y的工厂类的工厂方法用于生产系列Y下的产品族A和产品族B的产品;

设计案例:

基于上一个设计案例的背景,对英雄的皮肤进行进行抽象工厂模式的设计,同时增加国庆风格、中秋风格两个系列;英雄皮肤分为男式英雄皮肤

和女式英雄皮肤,将其设计为接口HeroDressInterface、HeroineDressInterface;国庆风格下的实现类为NationalHeroDress、NationalHeroineDress;

中秋风格下的实现类为MAHeroDress、MAHeroineDress;国庆、中秋两个系列对应的皮肤工厂类分别为NationalFactory、 MAFactory;这两个工厂类都实现了皮肤工厂接口;

HeroDressInterface接口具体代码如下:

    //男式英雄皮肤接口
    public interface HeroDressInterface
    {
        public HeroDressInterface produceHeroDress();
    }

HeroineDressInterface接口具体代码如下:

    //女式英雄皮肤接口
    public interface HeroineDressInterface
    {
        public HeroineDressInterface produceHeroineDress();

    //国庆系列男式英雄皮肤类
    public class NationalHeroDress implements HeroDressInterface
    {
        @Override
        public HeroDressInterface produceHeroDress()
        {
            System.out.println("国庆系列男式英雄皮肤");   
        }
    }
    //国庆系列女式英雄皮肤
    public class NationalHeroineDress implements HeroineDressInterface
    {
        @Override
        public HeroineDressInterface produceHeroineDress()
        {
            System.out.println("国庆系列女式英雄皮肤");   
        }
    }
    //中秋系列男式英雄皮肤类
    public class MAHeroDress implements HeroDressInterface
    {
        @Override
        public HeroDressInterface produceHeroDress()
        {
            System.out.println("中秋系列男式英雄皮肤");   
        }
    }
    //中秋系列女式英雄皮肤
    public class MAHeroineDress implements HeroineDressInterface
    {
        @Override
        public HeroineDressInterface produceHeroineDress()
        {
            System.out.println("中秋系列女式英雄皮肤");   
        }
    }
    //皮肤的实现接口
    public interface dressFactory
    {
        //获取男式英雄皮肤
        public HeroDressInterface produceHeroDre();
        //获取女式英雄皮肤
        public HeroineDressInterface produceHeroineDre();
    }
    //国庆系列皮肤工厂类
    public class nationalDressFactory implements dressFactory
    {
        @Override
        public HeroDressInterface produceHeroDre()
        {
            return new NationalHeroDress();
        }
        @Override
        public HeroineDressInterface produceHeroineDre()
        {
            return new NationalHeroineDress();
        }
    }
    //中秋系列皮肤工厂类
    public class maDressFactory implements dressFactory
    {
        @Override
        public HeroDressInterface produceHeroDre()
        {
            return new MAlHeroDress();
        }
        @Override
        public HeroineDressInterface produceHeroineDre()
        {
            return new MAHeroineDress();
        }
    }   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值