10.8.2内部类与控制框架(设计模式之模板方法)

这一小节为了说明内部类的用法,顺便带出了两个设计模式,一个是模板方法,一个是命令模式。
这也是我喜欢这本书的原因,作者总是能通过一些有意思的小例子,教会我们怎么使用JAVA的特性,并且将设计模式也融入其中。

《Think in JAVA》 这本书我是结合《大话设计模式》这本书,一起阅读的。《大话设计模式》将设计模式更通俗的讲了一遍。并且大话是国内作者写的,比起Think来说,不需要通过翻译。
哈哈,可能大神都是看英文原版的。

总之我在这里把大话的代码也附在这里,就当读书笔记吧。希望大家也能看懂。手动擦汗表情。

模板方法设计模式,主要的思想。以下为摘抄。
既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复。
设计模式总是将变化的事物与保持不变的事物分离开,在这个模式中,模板方法是保持不变的事物,而可覆盖的方法就是变化的事物。

先来看Think in JAVA中的例子。
Event类就是模板
其中的action()方法,是要在子类中覆盖的部分。

public abstract class Event {
    private long eventTime;
    protected final long delayTime;
    public Event(long delayTime) {
        this.delayTime = delayTime;
    }

    public void start() {
        eventTime = System.nanoTime() + delayTime;
    }

    public boolean ready() {
        System.out.println("eventTime : " + eventTime);
        return System.nanoTime() >= eventTime;
    }

    public abstract void action();
}

LightOn、LightOff 、WaterOn 、WaterOff 、ThermostatNight、ThermostatDay、Bell、Restart、Terminate这些内部类都继承了Event 类,他们都是Event类的子类。
通过覆盖action()方法,把重复的部分留在父类中。把变化的部分通过覆盖action()方法实现。

public class GreenhouseControls extends Controller {
    private boolean light = false;
    public class LightOn extends Event {


        public LightOn(long delayTime) {
            super(delayTime);
        }


        @Override
        public void action() {
            light = true;
        }
        public String toString() {
            return "Light is on";
        }
    }

    public class LightOff extends Event {


        public LightOff(long delayTime) {
            super(delayTime);
        }


        @Override
        public void action() {
            light = false;
        }
        public String toString() {return "Light is off";}
    }


    private boolean water = false;

    public class WaterOn extends Event {


        public WaterOn(long delayTime) {
            super(delayTime);
        }


        @Override
        public void action() {
            water = true;
        }

        public String toString() {return "Greenhouse water is on";}
    }

    public class WaterOff extends Event {


        public WaterOff(long delayTime) {
            super(delayTime);
        }


        @Override
        public void action() {
            water = false;
        }

        public String toString() {
            return "Greenhouse water is off";
        }
    }

    private String thermostat = "Day";

    public class ThermostatNight extends Event {

        public ThermostatNight(long delayTime) {
            super(delayTime);
        }

        @Override
        public void action() {
            thermostat = "Night";
        }

        public String toString() {
            return "Thermostat on night setting";
        }
    }

    public class ThermostatDay extends Event {


        public ThermostatDay(long delayTime) {
            super(delayTime);
        }


        @Override
        public void action() {
            thermostat = "day";
        }

        public String toString() {
            return "Thermostat on day Setting";
        }
    }


    public class Bell extends Event {

        public Bell(long delayTime) {
            super(delayTime);
        }

        @Override
        public void action() {
            addEvent(new Bell(delayTime));
        }

        public String toString() {
            return "Bing!";
        }
    }

    public class Restart extends Event {

        private Event[] eventList;

        public Restart(long delayTime, Event[] eventList) {
            super(delayTime);
            this.eventList = eventList;
            for(Event e : eventList)
                addEvent(e);
        }

        @Override
        public void action() {
            for(Event e : eventList) {
                e.start();
                addEvent(e);
            }
            start();
            addEvent(this);
        }
        public String toString() {
            return "Restarting system";
        }
    }

    public static class Terminate extends Event {

        public Terminate(long delayTime) {
            super(delayTime);
        }

        @Override
        public void action() {
            System.exit(0);
        }

        public String toString() {
            return "Terminating";
        }
    }
}

下面我们来看《大话设计模式》中的例子。
简单粗暴。

这里说模板类是一个试卷。↓↓↓

public abstract class TestPaper {
    public void testQuestion1() {
        System.out.println("杨过得到玄铁后给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】");
        System.out.println("a.球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
    }

    protected abstract String answer1();
}·

↓↓↓
这里先是继承模板类TestPaper
学生A的试卷只需要覆盖答案方法就好了,这里覆盖answer1()
↓↓↓

public class TestPaperA extends TestPaper {
    @Override
    protected String answer1() {
        return "b";
    }
}

↓↓↓
这里也同样继承模板类TestPaper
学生B的试卷只需要覆盖答案方法就好了,这里覆盖answer1()
↓↓↓

public class TestPaperB extends TestPaper {
    @Override
    protected String answer1() {
        return "c";
    }
}

小结

这里仅仅将不同的地方留在子类处理,想通的地方都在父类中。(也就是模板类中)

接下来是Main↓↓↓

public class Main {
    public static void main(String[] args) {
        TestPaper studentA = new TestPaperA();
        studentA.testQuestion1();
        System.out.println(studentA.answer1());


        TestPaper studentB = new TestPaperB();
        studentB.testQuestion1();
        System.out.println(studentB.answer1());
    }
}

输出↓↓↓

杨过得到玄铁后给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】
a.球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维
b
杨过得到玄铁后给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】
a.球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维
c

Process finished with exit code 0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容