当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 7 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 推荐阅读: 冒号和他的学生们
帖子发表于 : 2008-05-16 10:32 
论坛管理员

注册: 2005-03-27 0:06
帖子: 10116
系统: Ubuntu 12.04
送出感谢: 7
接收感谢: 128
1: http://www.blogjava.net/xyz98/archive/2 ... 97482.html
2: http://www.blogjava.net/xyz98/archive/2 ... 97629.html
3: http://www.blogjava.net/xyz98/archive/2 ... 97709.html
4: http://www.blogjava.net/xyz98/archive/2 ... 97955.html
5: http://www.blogjava.net/xyz98/archive/2 ... 98497.html
6: http://www.blogjava.net/xyz98/archive/2 ... 98601.html
7: http://www.blogjava.net/xyz98/archive/2 ... 98831.html
8: http://www.blogjava.net/xyz98/archive/2 ... 99100.html
9: http://www.blogjava.net/xyz98/archive/2 ... 99384.html
10: http://www.blogjava.net/xyz98/archive/2 ... 99616.html
11: http://www.blogjava.net/xyz98/archive/2 ... 99782.html
12: http://www.blogjava.net/xyz98/archive/2 ... 99909.html
13: http://www.blogjava.net/xyz98/archive/2 ... 00120.html

节选:
冒号清了清嗓子:“为尊重民意,也为避免消化不良,大家先放松一下。下面我们来个情景编程。”

“情景编程?没听说过,只听说过情景英语。”问号觉得新鲜。

“都是学语言嘛,有何两样?”冒号轻描淡写,“让我们试着用生活中的实例将一些编程范式串联起来。前面提到,OOP可以看作管理一个服务型公司,现在以餐馆为例,你们每人设计一类对象及其提供的服务。”

问号来了兴致:“我先来吧。构造一个前台接待员,负责迎客、引座、送客。”

句号很是不满:“还真不客气,上来就把最漂亮的对象抢走了。”

台下一阵笑声。

“我来构建最常见的服务员。”逗号一捋袖子,似乎准备开干的样子,“负责斟茶、写菜、上菜、换盘。”

“嗯,很熟练。”冒号一本正经。

句号实在得很:“我设计收银员,专管收帐、出具发票。”

引号颇为自豪:“我造一个技术含量最高的大厨,专门负责烹调。”

逗号不服:“你倒简单,那么高的技术含量,敢情炒肉和炖肉一个做法啊?”

引号自觉理亏:“那就负责蒸、煮、炒、炖吧。”

冒号为其辩护:“引号同学并没有错,可惜没能坚持。厨师只需提供一种服务:把纸上菜变成盘中菜,至于蒸、煮、炒、炖等具体做法纯属实现细节。”

叹号有点委屈:“唉,看来我只好做技术含量最低的厨工了,负责食品预加工、洗碗、打扫清洁。”

冒号将大家设计的类翻译成Java——
代码:
    // 前台接待员
    Class Receptionist
    {
        public void receive(Customer)        {…} // 迎客
        public void usher(Customer)          {…} // 引座
        public void send(Customer)           {…} // 送客
    }

    // 服务员
    Class Waiter
    {
        public void pourTea(Customer)        {…} // 斟茶
        public List<Order> write(Customer)   {…} // 写菜
        public void serve(Customer, Course)  {…} // 上菜
        public void exchangePlate(Customer)  {…} // 换盘
    }

    // 收银员
    Class Cashier
    {
        public void charge(Customer)         {…} // 收帐
        public void issueInvoice(Customer)   {…} // 出具发票
    }

    // 厨师
    Class Cook
    {
        public Course cook(Order)            {…} // 烹调
    }

    // 厨工
    Class KitchenHand
    {
        public void prepareFood()            {…} // 准备食品
        public void washDishes()             {…} // 洗碗
        public void clean()                  {…} // 打扫清洁
    }


“你们造人,我来造物。”冒号构造了一个餐馆的类——
代码:
    // 餐馆
    Class Restaurant
    {
        // 每当有顾客来访,返回该顾客
        private Customer accept() {…}

        // 为指定顾客提供所有的餐馆服务
        private void serve(Customer customer) {…}

        // 餐馆服务
        public void service()
        {
            while (true) // 无限循环,假设餐馆7×24小时营业
            {
                final Customer customer;
                if ((customer = accept() ) != null) // 某顾客来访
                {
                    serve(customer);  // 为该顾客提供服务
                }
            }
        }
    }


冒号解说道:“这里accept类似Socket的accept,属于堵塞呼叫(blocking call),意味着此方法将堵塞进程直至收到新数据。为简单计,把一行顾客当作一个Customer。大家对此段代码有何看法?”

“没什么,很简单啊。”逗号说完补充一句,“关键是serve方法的实现。”

“这里我们明显用到了两个范式,对象式和过程式。”冒号提示道。

引号会意:“应该还需要并发式。serve如果与service在同一线程中运行,那么餐馆只有等服务完一个Customer后才能服务后面的,这显然是荒唐的。”

“对极了!”冒号将“serve(customer);”改写为——
代码:
    // serve(customer);  // 错误地使用单线程!
    new Thread              // 构造一个线程
        (new Runnable()
        {
            public void run(){ Restaurant.this.serve(customer); }
        }).start();         // 启动该线程


冒号解释:“这回serve在新线程中运行,不会耽误Restaurant服务下一位Customer了。”

问号眼尖:“我注意到声明customer时前面加上了关键字final,有必要吗?”

“如果不用线程,是不必要的。”冒号回应道,“我们在建造线程时用到了实现Runnable接口的匿名类(anonymous class),它是涉及到局部变量customer的内部类(inner class),Java语法要求该局部变量必须是final类型。值得一提的是,这里不仅用到了并发式,而且与函数式也密切相关。”

“函数式?”逗号奇道。

“不错。”冒号坚定地点着头,“函数式的一个重要特征是:函数是头等公民(first-class citizen),即与其他基本数据类型一样,可以作为传递参数、作为其他函数返回值或与变量名绑定。闭包(closure)便是这样一种函数,并且能保留当初创建时周围的环境变量。以上匿名类本质上是函数serve的包装,经实例化后作为参数传入Thread的构造函数,并且记住了外部类的局部变量customer——这也是为什么它必须是final以保证不被重新赋值的原因。应该说这是一种OO化的闭包形式,预计在Java 7中它的用法会更简洁。”

句号自告奋勇:“我来具体实现serve吧。”

得到冒号的默许,句号在黑板上写下——
代码:
    private void serve(Customer customer)
    {
        // 找一个空闲的接待员
        Receptionist receptionist = findReceptionist();
        receptionist.receive(customer);
        receptionist.usher(customer);
        // 找一个空闲的服务员
        Waiter waiter = findWaiter();
        waiter.pourTea(customer);
        List<Order> orders = waiter.write(customer);
        // 将菜单交给一位厨师
        Cook cook = waiter.pass(orders);
        for (Order order : orders) // 厨师照单做菜
        {
            Course course = cook.cook(order);
            // 找一个空闲的服务员
            waiter = findWaiter();
            // 服务员上菜
            waiter.serve(customer, course);
            // 顾客开始享用
            customer.eat(course);
        }

        // 顾客用餐完毕。。。
        // 找一个空闲的收银员
        Cashier cashier = findCashier();
        cashier.charge(customer);
        cashier.issueInvoice(customer);
        // 找一个空闲的接待员
        receptionist = findReceptionist();
        receptionist.send(customer);
    }

句号写毕又复查一遍,拍拍手上的粉笔灰,心满意足地走下台来。

叹号提意见:“我的厨工没派上用场,应该在厨师烹调前调用KitchenHand的prepareFood方法。”

问号挑出另外的毛病:“在for循环中,厨师、服务员和顾客的行为应该在不同的线程中,厨师不可能等服务员上完一道菜或顾客吃完一道菜后才做下一道。”

“可能更复杂呢!”逗号也来凑热闹,“一位顾客点的几样菜可能分别由几位厨师同时做,每位厨师都在不同的线程中工作。”

引号更严谨:“还应有一个后台线程,让Waiter随时exchangePlate,让KitchenHand随时washDishes和clean,这样所有服务人员提供的服务都用上了。”

句号倒抽凉气:“估不到漏洞这么多,并发式真是无处不在啊。”

冒号指着引号:“刚才有人不满你的大厨职责过于简单,现在你来实现一下,也好显显技术含量。”

引号在台上摸了半天头,编出一段代码——
代码:
   Class Cook
    {
        public Course cook(Order order)
        {
            // 根据菜单查食谱
            Recipe recipe = lookupRecipe(order);
            // 找到食谱的烹调步骤
            List<Instruction> instructions = recipe.getInstructions();
            for (Instruction instruction : instructions)
            {
                follow(instruction); // 按食谱的指令操作
            }
        }
    }


“堂堂大厨原来是靠查食谱做菜的。”逗号揶揄道。

引号为难地说:“这不是在编程嘛,好端端的人脑,不得不去模拟电脑,完全搞倒了。”

“要设计会烹调的机器人,兴许还真得这样呢。”冒号笑道,“不过由于各种菜式组合繁多,如果每种菜都配菜谱未免太庞杂,如何精简呢?”

句号建议:“菜式成千上万,烹调技法相对少许多,不妨以技法为主线。”

“好主意!”冒号挑起大拇指,“如果把待加工的菜看作数据,技法看作算法,将数据与算法分离,以算法为中心,那是什么范式?”

“泛型式!”大家异口同声。

“至此我们已涉及了过程式、对象式、并发式、函数式和泛型式。”引号如数家珍,“还差逻辑式、元编程和切面式了。”

冒号把目光转向逗号:“写菜单并不容易,如果客人不直接点菜,你的服务员如何向他推荐?”

逗号答:“最简单的方法是报菜名,并一一询问客人。”

冒号皱眉:“这样你是简单了:一个迭代就搞定,可客人也该发火了。”

逗号赶紧修正:“先询问客人的口味、忌讳等等,再向他建议一些菜式。”

“这还差不多。”冒号眉头舒展开来,“考虑到客人的口味、忌讳等各有不同,餐馆的菜单也随时可能变化,如果把这些都硬编码(hardcode),代码将成为懒婆娘的裹脚——又臭又长又难维护。”

引号提议:“可以把这些信息预先存入数据库,届时用SQL查询。”

“想法很好,只是有一点难度。”冒号提醒道,“这些信息并非简单的对应关系,包含一些逻辑推理,甚至需要一些模糊判断。”

句号一拍大腿:“前面不是提到领域特定语言DSL吗?将所有规则用自定义的DSL编写,再利用元编程转换成C、Java之类的通用语言,不是很好吗?”

“棒极了!”冒号不吝赞词,“不过还有一种思路。我们可以搜集餐馆的菜式、顾客口味、忌讳以及各种菜与口味、忌讳之间的关系等等一系列事实和规则,用规则语言(Rule Language)如RuleML、SWRL、Jess等来描述,通过规则引擎(Rule Engine)来导出符合顾客需求的菜肴。这种方式将业务规则与应用程序分离、将知识与逻辑实现分离,是SoC原理的一种应用,同时也是一种逻辑式编程。”

问号关心地问:“这些规则引擎与Java程序兼容吗?”

冒号回答:“不少规则引擎用Java实现或专为Java平台设计,如Jess、Drools、JLisa等,另外Sun还发布了javax.rules API (JSR 94)以统一对各类引擎的访问接口。”

讲到此处,每个人都意识到,只剩下最后一个范式了。

冒号提出新问题:“假如餐馆经理接到顾客投诉,反映服务人员态度不好,卫生状况也不理想,应该怎么办?”

问号抢先说:“首先我的接待员在receive时要笑容可掬地对顾客说:‘欢迎光临!’,在send时要对顾客鞠躬:‘请慢走,欢迎下次再来’”

逗号接着说:“我的服务员在上完菜后应对客人说:‘请慢用’,句号的收银员也应加些礼貌用语,让人家高高兴兴地掏钱。”

句号补充道:“服务员在serve前、厨师在cook前应洗手,厨工在washDishes后应对餐具消毒。”

冒号紧接着问:“如果餐馆对礼貌规范或卫生标准做修改,必然要牵扯不同类中的不同的方法,维护起来很不方便,怎样才能有效地解决这个问题呢?”

答案已经昭然若揭了。

冒号干脆自问自答:“不错,正是用切面式编程。只要创立两个Aspect:Etiquette和Sanitation,分别负责礼貌规范和卫生标准方面的事务。一旦某一方面的要求发生变化,比如餐馆来了外宾,或者碰上非典或禽流感,只需在相应的Aspect模块中作调整:将礼貌用语换成英语或者提高卫生标准等等。如果采用runtime AOP,甚至还可在运行期选择激活或禁用这些Aspect。”


页首
 用户资料  
 
2 楼 
 文章标题 :
帖子发表于 : 2008-05-16 10:37 
头像

注册: 2007-10-19 14:51
帖子: 4953
地址: 深圳
送出感谢: 0 次
接收感谢: 2
呵呵,面向对象


_________________
Nothing 有事请发邮件到 yms541 AT gmail.com
alias 爱慕颇雷尔='mplayer'


页首
 用户资料  
 
3 楼 
 文章标题 :
帖子发表于 : 2008-05-16 10:44 
头像

注册: 2006-04-12 20:05
帖子: 8495
地址: 杭州
送出感谢: 0 次
接收感谢: 8
哈哈,先顶再看..


_________________
关注我的blog: ε==3


页首
 用户资料  
 
4 楼 
 文章标题 :
帖子发表于 : 2008-05-16 11:13 
头像

注册: 2007-04-25 13:12
帖子: 2838
送出感谢: 0 次
接收感谢: 0 次
不错
学习一下 :D


_________________
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS


页首
 用户资料  
 
5 楼 
 文章标题 :
帖子发表于 : 2008-05-16 14:50 
头像

注册: 2006-09-04 10:45
帖子: 765
送出感谢: 0 次
接收感谢: 0 次
UP


页首
 用户资料  
 
6 楼 
 文章标题 :
帖子发表于 : 2008-05-16 18:40 
头像

注册: 2007-10-21 16:41
帖子: 1289
地址: GD
送出感谢: 0 次
接收感谢: 0 次
ding


页首
 用户资料  
 
7 楼 
 文章标题 :
帖子发表于 : 2008-05-16 18:50 
头像

注册: 2005-08-01 9:14
帖子: 3666
送出感谢: 0 次
接收感谢: 0 次
8)


_________________
Gedanken ohne Inhalt sind leer .Anschauungen ohne Begriffe sind blind.


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 7 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 3 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译