美文网首页Android设计模式Android技术知识Android开发经验谈
Android设计模式之(4)----工厂方法模式

Android设计模式之(4)----工厂方法模式

作者: Ch3r1sh | 来源:发表于2017-08-16 15:22 被阅读51次

    工厂方法模式


    比如富士康是一个工厂,为其他外部厂商提供相同或者不同的产品,而外部厂商不用关心富士康内部的实现过程,只需要接受结果即可。如果有新的产品,也只需要告诉富士康,富士康负责生产输出就好。

    因此工厂模式可大幅度降低模块之间的耦合,加强扩展性。

    应用场景

    需要生成一个或者多个复杂对象的具体实现

    工厂模式分类

    • 工厂方法模式
      • 标准工厂
      • 简单工厂
      • 反射工厂
      • 缓存工厂
      • 私有工厂
    • 抽象工厂模式

    本文主要介绍工厂方法模式。

    工厂方法模式特点

    • 一个抽象类可以实现多个具体类

    具体实现

    Q:使用工厂模式来判断一个程序猿他是具体的什么样的程序猿(PHP,Android,iOS,Java等等)

    (一)标准工厂方法

    1.建立一个接口来获取程序猿类型

    public interface CodeMonkey {
        public  void showCodeMonkeyType();//展示是什么类型的程序猿
    }
    
    

    2.实现接口生成不同类型的程序猿

    Android程序猿:

    public class AndroidCodeMonkey implements  CodeMonkey {
        @Override
        public void showCodeMonkeyType() {
            System.out.println("我是Android攻城狮");
        }
    }
    
    

    iOS程序猿:

    public class IosCodeMonkey implements  CodeMonkey {
        @Override
        public void showCodeMonkeyType() {
            System.out.print("我是iOS攻城狮");
        }
    }
    
    

    3.建立抽象的工厂接口

    public abstract class Factory {
        public abstract CodeMonkey showCodeMonkeyType() ;
    }
    
    

    4.通过抽象的工厂接口进行具体类的实现

    public class AndroidMonkeyFactory extends Factory {
    
        @Override
        public CodeMonkey showCodeMonkeyType() {
            return new AndroidCodeMonkey();
        }
    }
    
    public class IosMonkeyFactory extends Factory {
        @Override
        public CodeMonkey showCodeMonkeyType() {
            return new IosCodeMonkey();
        }
    }
    

    5.具体调用

    CodeMonkey codeMonkey = new AndroidCodeMonkey();
            codeMonkey.showCodeMonkeyType();
    
            new IosCodeMonkey().showCodeMonkeyType();
    
    

    6.输出结果

    我是Android攻城狮
    
    我是iOS攻城狮
    
    

    程序猿(产品)在创建过程中都是通过接口来进行生成,生成某一类型程序猿时降低了使用者和产品本身耦合

    (二)简单工厂模式(静态工厂模式)

    静态工厂的方法是静态的,不允许外部进行扩展更改,如果有内容的更改需要对当前静态工厂进行更改。

    代码示例:

    public class CodeMonkeyEasyFactory {
        public final static String GENERATE_IOS = "android";
        public final static String GENERATE_ANDROID = "ios";
        public static CodeMonkey generateCodeMonkey(String flag) throws Exception {
            CodeMonkey codeMonkey = null;
            switch (flag){
                case GENERATE_ANDROID:
                    codeMonkey =  new AndroidCodeMonkey();
                    break;
                case GENERATE_IOS:
                    codeMonkey =  new IosCodeMonkey();
                    break;
    
                default:
                    throw new Exception("UNDEFINED FLAG");
            }
            return codeMonkey;
        }
    }
    

    上述静态工厂在内部已经定义了iOS和Android的静态常亮,使用过程中只需要外部传入具体的数值,内部进行判断即可,但是若有新的程序猿产生,除了实现具体的程序猿,还需要对静态工厂扩展增加。
    外部调用:

    CodeMonkeyEasyFactory.generateCodeMonkey(CodeMonkeyEasyFactory.GENERATE_ANDROID).showCodeMonkeyType();
    CodeMonkeyEasyFactory.generateCodeMonkey(CodeMonkeyEasyFactory.GENERATE_IOS).showCodeMonkeyType();
    

    显示结果:

    我是Android攻城狮
    
    我是iOS攻城狮
    
    
    (三)反射工厂

    只需要实现具体的产品类型而不需要修改工厂,通过反射抛到上层直接让外部使用获取。

    代码示例:

    1.泛型类型约束将具体类型抛到上层工厂进行处理

    public abstract class IGenerator {
        public abstract <T extends CodeMonkey>T generateCodeMonkey(Class<T> clazz) throws Exception;
    }
    
    

    2.实现具体产品内容

    public class CodeMonkeyReflexFactory extends IGenerator {
        @Override
        public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
            CodeMonkey codeMonkey = null;
            codeMonkey = (CodeMonkey) Class.forName(clazz.getName()).newInstance();
            return (T)codeMonkey;
        }
    }
    
    

    调用方式:

     new CodeMonkeyReflexFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
    

    显示结果:

    我是Android攻城狮
    

    (四)缓存工厂

    将复杂对象或者频繁使用的内容作为一个长期的存储,再次使用时直接进行提取

    代码示例:

    public class CodeMonkeyCacheFactory  extends IGenerator {
        private Map<String, CodeMonkey> map = new HashMap<>();
    
        @Override
        public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
            CodeMonkey CodeMonkey = null;
            if (map.containsKey(clazz.getName()))
                CodeMonkey = map.get(clazz.getName());
            else {
                CodeMonkey = (CodeMonkey) Class.forName(clazz.getName()).newInstance();
                map.put(clazz.getName(), CodeMonkey);
            }
            return (T) CodeMonkey;
        }
    }
    

    将具体的产品类型存储于hasmap,再次使用时可直接提取使用。

    调用方式:

     new CodeMonkeyCacheFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
     
    

    显示结果:

    我是Android攻城狮
    

    (五) 私有产品构造

    限制外部使用new XXX()的方式进行创建

    public class CodeMonkeyPrivateFactory extends IGenerator {
        public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
            CodeMonkey iPhone = null;
            Class phone = Class.forName(clazz.getName());
            //拿到构造器不检测权限
            phone.getDeclaredConstructor().setAccessible(true);
            iPhone = (CodeMonkey) phone.newInstance();
            return (T) iPhone;
        }
    }
    

    调用方式:

     new CodeMonkeyPrivateFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
    

    显示结果:

    我是Android攻城狮
    

    总结

    以上就是工程模式的介绍.降低模块耦合,提高扩展性,有新的产品内容出现只需要扩展工厂即可完成。

    github代码地址

    相关文章

      网友评论

        本文标题:Android设计模式之(4)----工厂方法模式

        本文链接:https://www.haomeiwen.com/subject/ljvirxtx.html