<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### [內部類與控制框架](https://lingcoder.gitee.io/onjava8/#/book/11-Inner-Classes?id=%e5%86%85%e9%83%a8%e7%b1%bb%e4%b8%8e%e6%8e%a7%e5%88%b6%e6%a1%86%e6%9e%b6) 在將要介紹的控制框架(control framework)中,可以看到更多使用內部類的具體例子。 應用程序框架(application framework)就是被設計用以解決某類特定問題的一個類或一組類。要運用某個應用程序框架,通常是繼承一個或多個類,并覆蓋某些方法。在覆蓋后的方法中,編寫代碼定制應用程序框架提供的通用解決方案,以解決你的特定問題。這是設計模式中模板方法的一個例子,模板方法包含算法的基本結構,并且會調用一個或多個可覆蓋的方法,以完成算法的動作。設計模式總是將變化的事物與保持不變的事物分離開,在這個模式中,模板方法是保持不變的事物,而可覆蓋的方法就是變化的事物。 控制框架是一類特殊的應用程序框架,它用來解決響應事件的需求。主要用來響應事件的系統被稱作*事件驅動*系統。應用程序設計中常見的問題之一是圖形用戶接口(GUI),它幾乎完全是事件驅動的系統。 要理解內部類是如何允許簡單的創建過程以及如何使用控制框架的,請考慮這樣一個控制框架,它的工作就是在事件“就緒”的時候執行事件。雖然“就緒”可以指任何事,但在本例中是指基于時間觸發的事件。接下來的問題就是,對于要控制什么,控制框架并不包含任何具體的信息。那些信息是在實現算法的`action()`部分時,通過繼承來提供的。 首先,接口描述了要控制的事件。因為其默認的行為是基于時間去執行控制,所以使用抽象類代替實際的接口。下面的例子包含了某些實現: ~~~ // innerclasses/controller/Event.java // The common methods for any control event package innerclasses.controller; import java.time.*; // Java 8 time classes public abstract class Event { private Instant eventTime; protected final Duration delayTime; public Event(long millisecondDelay) { delayTime = Duration.ofMillis(millisecondDelay); start(); } public void start() { // Allows restarting eventTime = Instant.now().plus(delayTime); } public boolean ready() { return Instant.now().isAfter(eventTime); } public abstract void action(); } ~~~ 當希望運行**Event**并隨后調用`start()`時,那么構造器就會捕獲(從對象創建的時刻開始的)時間,此時間是這樣得來的:`start()`獲取當前時間,然后加上一個延遲時間,這樣生成觸發事件的時間。`start()`是一個獨立的方法,而沒有包含在構造器內,因為這樣就可以在事件運行以后重新啟動計時器,也就是能夠重復使用**Event**對象。例如,如果想要重復一個事件,只需簡單地在`action()`中調用`start()`方法。 `ready()`告訴你何時可以運行`action()`方法了。當然,可以在派生類中覆蓋`ready()`方法,使得**Event**能夠基于時間以外的其他因素而觸發。 下面的文件包含了一個用來管理并觸發事件的實際控制框架。**Event**對象被保存在**List** 類型(讀作“Event 的列表”)的容器對象中,容器會在[集合](https://lingcoder.gitee.io/onjava8/#/)中詳細介紹。目前讀者只需要知道`add()`方法用來將一個**Event**添加到**List**的尾端,`size()`方法用來得到**List**中元素的個數,foreach 語法用來連續獲取**List**中的**Event**,`remove()`方法用來從**List**中移除指定的**Event**。 ~~~ // innerclasses/controller/Controller.java // The reusable framework for control systems package innerclasses.controller; import java.util.*; public class Controller { // A class from java.util to hold Event objects: private List<Event> eventList = new ArrayList<>(); public void addEvent(Event c) { eventList.add(c); } public void run() { while(eventList.size() > 0) // Make a copy so you're not modifying the list // while you're selecting the elements in it: for(Event e : new ArrayList<>(eventList)) if(e.ready()) { System.out.println(e); e.action(); eventList.remove(e); } } } ~~~ `run()`方法循環遍歷**eventList**,尋找就緒的(`ready()`)、要運行的**Event**對象。對找到的每一個就緒的(`ready()`)事件,使用對象的`toString()`打印其信息,調用其`action()`方法,然后從列表中移除此**Event**。 注意,在目前的設計中你并不知道**Event**到底做了什么。這正是此設計的關鍵所在—"使變化的事物與不變的事物相互分離”。用我的話說,“變化向量”就是各種不同的**Event**對象所具有的不同行為,而你通過創建不同的**Event**子類來表現不同的行為。 這正是內部類要做的事情,內部類允許: 1. 控制框架的完整實現是由單個的類創建的,從而使得實現的細節被封裝了起來。內部類用來表示解決問題所必需的各種不同的`action()`。 2. 內部類能夠很容易地訪問外部類的任意成員,所以可以避免這種實現變得笨拙。如果沒有這種能力,代碼將變得令人討厭,以至于你肯定會選擇別的方法。 考慮此控制框架的一個特定實現,如控制溫室的運作:控制燈光、水、溫度調節器的開關,以及響鈴和重新啟動系統,每個行為都是完全不同的。控制框架的設計使得分離這些不同的代碼變得非常容易。使用內部類,可以在單一的類里面產生對同一個基類**Event**的多種派生版本。對于溫室系統的每一種行為,都繼承創建一個新的**Event**內部類,并在要實現的`action()`中編寫控制代碼。 作為典型的應用程序框架,**GreenhouseControls**類繼承自**Controller**: ~~~ // innerclasses/GreenhouseControls.java // This produces a specific application of the // control system, all in a single class. Inner // classes allow you to encapsulate different // functionality for each type of event. import innerclasses.controller.*; public class GreenhouseControls extends Controller { private boolean light = false; public class LightOn extends Event { public LightOn(long delayTime) { super(delayTime); } @Override public void action() { // Put hardware control code here to // physically turn on the light. light = true; } @Override public String toString() { return "Light is on"; } } public class LightOff extends Event { public LightOff(long delayTime) { super(delayTime); } @Override public void action() { // Put hardware control code here to // physically turn off the light. light = false; } @Override 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() { // Put hardware control code here. water = true; } @Override public String toString() { return "Greenhouse water is on"; } } public class WaterOff extends Event { public WaterOff(long delayTime) { super(delayTime); } @Override public void action() { // Put hardware control code here. water = false; } @Override 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() { // Put hardware control code here. thermostat = "Night"; } @Override public String toString() { return "Thermostat on night setting"; } } public class ThermostatDay extends Event { public ThermostatDay(long delayTime) { super(delayTime); } @Override public void action() { // Put hardware control code here. thermostat = "Day"; } @Override public String toString() { return "Thermostat on day setting"; } } // An example of an action() that inserts a // new one of itself into the event list: public class Bell extends Event { public Bell(long delayTime) { super(delayTime); } @Override public void action() { addEvent(new Bell(delayTime.toMillis())); } @Override 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(); // Rerun each event addEvent(e); } start(); // Rerun this Event addEvent(this); } @Override 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); } @Override public String toString() { return "Terminating"; } } } ~~~ 注意,**light**,**water**和**thermostat**都屬于外部類**GreenhouseControls**,而這些內部類能夠自由地訪問那些字段,無需限定條件或特殊許可。而且,`action()`方法通常都涉及對某種硬件的控制。 大多數**Event**類看起來都很相似,但是**Bell**和**Restart**則比較特別。**Bell**控制響鈴,然后在事件列表中增加一個**Bell**對象,于是過一會兒它可以再次響鈴。讀者可能注意到了內部類是多么像多重繼承:**Bell**和**Restart**有**Event**的所有方法,并且似乎也擁有外部類**GreenhouseContrlos**的所有方法。 一個由**Event**對象組成的數組被遞交給**Restart**,該數組要加到控制器上。由于`Restart()`也是一個**Event**對象,所以同樣可以將**Restart**對象添加到`Restart.action()`中,以使系統能夠有規律地重新啟動自己。 下面的類通過創建一個**GreenhouseControls**對象,并添加各種不同的**Event**對象來配置該系統,這是命令設計模式的一個例子—**eventList**中的每個對象都被封裝成對象的請求: ~~~ // innerclasses/GreenhouseController.java // Configure and execute the greenhouse system import innerclasses.controller.*; public class GreenhouseController { public static void main(String[] args) { GreenhouseControls gc = new GreenhouseControls(); // Instead of using code, you could parse // configuration information from a text file: gc.addEvent(gc.new Bell(900)); Event[] eventList = { gc.new ThermostatNight(0), gc.new LightOn(200), gc.new LightOff(400), gc.new WaterOn(600), gc.new WaterOff(800), gc.new ThermostatDay(1400) }; gc.addEvent(gc.new Restart(2000, eventList)); gc.addEvent( new GreenhouseControls.Terminate(5000)); gc.run(); } } ~~~ 輸出為: ~~~ Thermostat on night setting Light is on Light is off Greenhouse water is on Greenhouse water is off Bing! Thermostat on day setting Bing! Restarting system Thermostat on night setting Light is on Light is off Greenhouse water is on Bing! Greenhouse water is off Thermostat on day setting Bing! Restarting system Thermostat on night setting Light is on Light is off Bing! Greenhouse water is on Greenhouse water is off Terminating ~~~ 這個類的作用是初始化系統,所以它添加了所有相應的事件。**Restart**事件反復運行,而且它每次都會將**eventList**加載到**GreenhouseControls**對象中。如果提供了命令行參數,系統會以它作為毫秒數,決定什么時候終止程序(這是測試程序時使用的)。 當然,更靈活的方法是避免對事件進行硬編碼。 這個例子應該使讀者更了解內部類的價值了,特別是在控制框架中使用內部類的時候。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看