zoukankan      html  css  js  c++  java
  • 柔性多态:消除多态中父子类的关联性

    在说明柔性多态之前先看看下面多态的设计

    一般常规的多态程序设计,首先定义多态接口

    public interface IShape3 {
        public float getArea();
    }

    然后在实体类中重写多态函数

    public class Circle3 implements IShape3 {
        float r;
        public Circle3(float r){
            this.r = r;
        }
        public float getArea(){
            return r*r*(float)Math.PI;
        }
    }
    public class Rect3 implements IShape3 {
        private float width,height;
        public Rect3(float width,float height){
            this.width = width;
            this.height = height;
        }
        public float getArea(){
            return width*height;
        }
    }

    客户端通过动态绑定对接口编程实现了求圆或长方形面积功能。但是考虑一个问题,如果以后需要求图形的周长,那上面这个例子该如何修改?

    思路是:重新定义接口IShape3,添加所需要的接口函数(求周长),然后再在继承该接口的对象(Circle3和Rect3)中再实现函数功能。

    这样做的后果就是使接口以及实现模块,客户端程序都需要重新修改并且重新编译。但是在实际开发维护中,我们只希望仅仅在底层具体模块功能可以修改并编译,

    而接口,上层模块以及客户端程序不需要更改或重新编写。

    由此可以看到普通多态的局限性:如果接口函数内容发生变化,那么相应的各实现子类必须发生变化,导致相关联的各级模块必须重新编写和编译。而造成原因莫过于父类与自己的多态函数关联过强。

    柔性多态的设计就是正是为了消除这种局限性,下面对上面提到的例子加以“改造”。

    定义柔性多态接口

    public interface IShape2 {
        public Object dispatch(int nID,Object in);
    }

    具体实现类

    public class Circle2 implements IShape2{
        public float r;
        public Circle2(float r){
            this.r = r;
        }
        public Object dispatch(int nId,Object in){
            Object obj = null;
            switch (nId){
                case 0:
                    obj = getArea(in) ;break;
                case 1:
                    obj = getPerimeter(in);break;
            }
            return obj;
        }
        Object getArea(Object in){
            float area = (float)Math.PI*r*r;
            return new Float(area);
        }
        Object getPerimeter(Object in){
            float len = (float)Math.PI*r*2.0f;
            return new Float(len);
        }
    }

    柔性多态的设计思想如下:

    1.接口内容固定,如上面IShape2中仅仅定义一个多态接口方法dispatch()

    2.子类中重写动态函数dispatch仅仅起到转发作用,且转发的具体函数都不是多态函数。这与第一个例子中多态接口编程思想不一致。

    假若现在需要添加新的功能,如求内接三角形的周长。现在只需要在Circle2类中添加一个普通方法getTriLength(),并且在多态函数中添加一个case开关,调用getTriLength()就可以了。

    而对接口IShape2根本没有修改。从而削弱了接口类和实现类的强关联,这就是实现柔性多态的关键。

    package interfaceAndAbstract.Polymorphism;
    
    /**
     * Created by lenovo on 2017/4/15.
     */
    public class Circle2 implements IShape2{
        public float r;
        public Circle2(float r){
            this.r = r;
        }
        public Object dispatch(int nId,Object in){
            Object obj = null;
            switch (nId){
                case 0:
                    obj = getArea(in) ;break;
                case 1:
                    obj = getPerimeter(in);break;
                case 2:
                    obj = getTriLength(in);break;
            }
            return obj;
        }
        Object getArea(Object in){
            float area = (float)Math.PI*r*r;
            return new Float(area);
        }
        Object getPerimeter(Object in){
            float len = (float)Math.PI*r*2.0f;
            return new Float(len);
        }
        Object getTriLength(Object in){
            //具体实现代码
            return null;
        }
    }
    View Code

    下面分析一下dispatch()方法的参数理解

    1.上面例子中2个参数,整型的普通功能号nID,输入参数in,类型是Object,相当于泛型编程,使程序更加灵活。

    2.改函数的返回值是Object对象,若为null,表明计算失败;若not null,则在强调方用强制类型转换才能得到需要的结果。

    测试类

    public class Test {
        public static void main(String[] args) {
            IShape2 obj = new Circle2(10.0f);
            Float result = (Float)obj.dispatch(1,null);
            System.out.println("半径10圆形面积:" + result.floatValue());
        }
    }

    完善:根据nID来获得执行函数并不友好,对于使用者不好去记住每个功能的ID。因此可以在接口中定义一个方法public int query(String strID)

    在子类中实现,通过方法名获得nID,再由nID来获得执行函数。

    总结:固化父类接口函数定义,子类通过重写多态派发函数,这是柔性多态的基本设计思想。

  • 相关阅读:
    树形dp--P2014 [CTSC1997]选课
    背包变形--P1759 通天之潜水
    区间dp--P1880 [NOI1995]石子合并
    动态规划--P2758 编辑距离
    筛法--CF449C Jzzhu and Apples
    BZOJ3998: [TJOI2015]弦论(后缀自动机,Parent树)
    BZOJ3530: [Sdoi2014]数数(Trie图,数位Dp)
    BZOJ1444: [Jsoi2009]有趣的游戏(Trie图,矩乘)
    BZOJ1195: [HNOI2006]最短母串(Trie图,搜索)
    BZOJ3238: [Ahoi2013]差异(后缀数组)
  • 原文地址:https://www.cnblogs.com/lateink/p/6716377.html
Copyright © 2011-2022 走看看