23种内功之--工厂模式

作者: MinuitZ | 来源:发表于2017-11-02 16:14 被阅读12次

    定义: 定义一个创建对象等借口 , 让子类决定实现哪个类
    其实说白了 , 也就是一组行为相似但细节不同的类 , 可以通过普通的继承来创建不同的对象 , 而工厂模式就是讲这种普通的继承更好的管理了起来

    我的理解:

    概括一句话就是: 抽象工厂返回抽象产品, 具体工厂生产具体产品
    这里涉及到四个名词

    1. 抽象工厂: 所有工厂的父类
    2. 具体工厂: 工厂的具体实现 , 包含业务逻辑
    3. 抽象产品: 产品的父类 , 在工厂中被创建
    4. 具体产品: 产品的具体实现.
      emmm 还是有点乱哈? 先上个图然后慢慢说

    场景模拟

    火影忍者中很多忍术都被记载在卷轴里面 , 忍者们可以通过阅读并修炼, 从而学习到忍术.
    一位下忍在训练中 , 要完成一个忍术的过程是

    1. 回忆所学的忍术的结印顺序
    2. 结印
    3. 释放忍术
      所以我们以卷轴为工厂 , 以忍术为产品来举例子 , 首先对应一下角色的关系
    • 抽象工厂----- 卷轴仓库
    • 具体工厂----- 具体的某一本卷轴
    • 抽象产品----- 忍术(区分于体术的概念)
    • 具体产品----- 具体的某种忍术
    1. 编写卷轴的类(抽象工厂)
    public abstract class WaterScrolls {
        public abstract <T extends Ninjutsu> T readMethod(Class<T> clazz) throws ClassNotFoundException;
    }
    

    这是一本水遁的卷轴 , 卷轴中有"阅读"这个抽象方法. 这里传入的参数为字节码文件 , 在重写方法中需要使用反射 . 返回值为忍术泛型 , 也对应到上文所说的抽象工厂返回抽象产品

    2.编写忍术类(抽象产品)
    public abstract class Ninjutsu {
        public abstract void read(); //回忆
        public abstract void ready();//结印
        public abstract void go();//释放
    }
    

    一个忍术需要完成的三个阶段为: 回忆, 结印 , 释放

    准备好了两个工厂 ,就可以具体的实现了

    3. 编写阅读忍术的类(具体工厂)
    public class ReadScrolls extends WaterScrolls {
        @Override
        public <T extends Ninjutsu> T readMethod(Class<T> clazz) {
            Ninjutsu ni = null;
            try {
                ni = (Ninjutsu) Class.forName(clazz.getName()).newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return (T) ni;
        }
    }
    

    在WaterScrolls中使用到了反射 , 在这里之需要传入忍术的class文件 , 返回值为忍术类的子类 , 也就是我们刚开始说到的 具体工厂制造具体产品

    4. 编写具体的忍术类(具体产品)

    这里选择两个忍术 , 水遁水乱波和水遁水鲛弹(其他的结印太长了)

    //水乱波类继承了忍术类
    public class WaterWave extends Ninjutsu{
        @Override
        public void read() {
            Log.e("水遁: 水乱波: ", "辰-丑-卯");
        }
    
        @Override
        public void ready() {
            Log.e( "ready: ","辰-丑-卯" );
        }
    
        @Override
        public void go() {
            Log.e("go: ","喷水" );
        }
    }
    
    //水遁水鲛弹
    public class WaterShark extends Ninjutsu{
        @Override
        public void read() {
            Log.e("水遁 水鲛弹术: ","寅—丑—辰—卯—酉—辰—未 " );
        }
    
        @Override
        public void ready() {
            Log.e( "ready: ","寅—丑—辰—卯—酉—辰—未" );
        }
    
        @Override
        public void go() {
            Log.e("go: ","水鲛弹" );
        }
    }
    
    使用方法

    有了上面的一系列的构造 , 我们可以从卷轴类中得到忍术 , 并使用忍术 , 这里写了battle类来模拟忍着对战

    public class Battle {
    
        public void doSomeThing(){
            //第一回合 , 正常的流程
            Ninjutsu firstRound=new WaterWave();
            firstRound.read();
            firstRound.ready();
            firstRound.go();
    
            //第二回合, 下忍早已学会忍术, 直接结印
            Ninjutsu secondRound=new WaterShark();
            secondRound.ready();
            secondRound.go();
        }
    }
    

    看到这里可能有人又要问了...... 我可以直接去new一个对象 , 在对象中去初始化啊 , 为什么还要用设计模式呢? 这里的工厂模式提供了一个模板, 我们新添加的产品在继承模板的情况下可以很方便的完成修改 , 如果一个一个的new的话 , 势必会有忘掉参数的风险 , 可维护性很低; 甚至可以新建一些抽象产品来完成产品类的扩展.

    所以 , 如果在面对一些复杂但是相似的对象的时候 , 你可以试试工厂模式

    相关文章

      网友评论

        本文标题:23种内功之--工厂模式

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