文章吧-经典好文章在线阅读:《A Little Java, A Few Patterns》读后感摘抄

当前的位置:文章吧 > 经典文章 > 经典美文 > 经典精选 >

《A Little Java, A Few Patterns》读后感摘抄

2022-04-26 03:02:12 来源:文章吧 阅读:载入中…

《A Little Java, A Few Patterns》读后感摘抄

  《A Little Java, A Few Patterns》是一本由Matthias Felleisen / Daniel P. F著作,The MIT Press出版的Paperback图书,本书定价:USD 28.00,页数:194,特精心从网络上整理的一些读者的读后感,希望对大家能有帮助。

  《A Little Java, A Few Patterns》精选点评:

  ●抽象,框架。出现accept方法的时候,惊呆了

  ●入门的书籍

  ●看了两章,看不下去了。。。

  ●略读了下。例程是伪装成Java的Lisp。似是一本向函数编程者介绍面向对向的书。

  ●刚开始的时候,以为是在看函数式语言,因为new一个新的Object就像是在创建一个list一样,一层叠一层,然后就是讲解为什么需要一个visitor类,当datatype的变种变得越来越多的时候,如果要对每一种都添加一个函数的话,那就需要在不同的类中去添加并且要照顾到变种之间的关系,这就萌生了把所有变种的同名函数集中到一起,那就方便互相查看与验证。再然后就是变种的方法函数只需要一个accept就可以了,然后调用一个visitor进行工作,等于是外包工作给任意多的有功能的函数。 为什么需要外包工作给visitor,那就是没人能一开始就写出完整无缺的程序,随着需求的修改,需要变动程序,那就是visitor pattern发挥作用的时候,可以单独的增加与原来变种平行的类,并且类之间可以互调……

  ●并没有读完。。反正就是不想读了,直接去搜了几个visitor pattern的教程看

  ●非常自然的带出一些概念和 Pattern

  ●一点面向对象,一点函数式,一点设计模式的混杂,适合不了解这三个概念的新手读

  ●有趣,順手膜一發Matthias。

  ●虽然书有点老(当时的Java甚至没有泛型),但是依然讲透了访问者模式,比较惊喜的是对表达式问题的解决,后续推荐看看Neu类似面向对象课程的课件。

  《A Little Java, A Few Patterns》读后感(一):java和visitor模式

  介绍java中实现面向对象的基本元素

  通过一些列的问题比如:每个类里面方法过多导致代码难懂(基本上就是继承的问题),太多类似的代码,通过里面java里面提供一些语言规则实现了一个visitor模式以及不断的精确来解决,赞!

  《A Little Java, A Few Patterns》读后感(二):用函数式的观点看Java

  看本书源于王垠某篇博客的推荐。

  这本书很薄,一天看完了。

  主要还是面向已经接触过函数式编程,但是是OO的初学者的同学,介绍了多态,继承,封装等OO的概念,如果你没有接触过OO,作者的讲解方式可谓相当的简洁明了。

  直到最后一章才引入了更改实例变量内容的概念,之前都是以一种偏向函数式编程的思路介绍。

  整体来说,还是写的很好的一本书,不过对于接触过函数式和面向对象编程的,基本也没有什么新东西获得。

  《A Little Java, A Few Patterns》读后感(三):Little书 不Little

  当然了书是没有搞到正版的,也没找到清晰的PDF版的.

  书延续了Little系列的风格.一问一答.简洁 xx.花了三个晚上看完的.虽然书书用Java写的但是感觉不想一般那样用.感觉像FP的用法.函数没有副作用.什么东东都new一下.当然到最后一章讲到了改变对象内部值的用法.

  内容的话,基本书讲了一个关于.访问者(visitor)模式.当然不是像四人帮那样直接给出定义啥的,也不给个循序渐渐的原因.书中还讲到了.一个没前端的解释器.然后同样的代码怎样使用于Set的(开始是Int).

  第一次写书评 o(∩_∩)o .

  .看书的时候是在晚上.但是书中基本是 沙拉,水果啥的.看得肚子饿死了.

  《A Little Java, A Few Patterns》读后感(四):functional Java 函数式版的Java

  我也是从王垠博客中知道这本书,花了一周把这本书陆陆续续看完了,下面简单列举一些体会:

  首先我想说下我是如何看这本书的:

  就像这本书一开始说的,不要一口气把这本书读完,这本书虽然没什么特别难理解的知识点,但是如果和看小说一样,一目十行,相信不会有太大收获。我一开始一口气看了前5章,后面实在看不下去了,有些摸不着头脑,于是又重新返工,从头开始,下班的晚上看,一天一章,在 Eclipse 里面敲敲书中的代码,一周下来把这本书拿下来,效果还不错。

  还要说一点的就是本书用了大量食物名来做demo,作为一名中国人,表示很无奈,很多单词都不知道,大家在阅读本书时最好查下相关类的中文含义,要不后面不知道作者要表达什么意思。

  其次关于本书的内容,主要的核心点就是 visitor 模式,这方法很强,之前在 sicp 时(习题2.76)也遇到过类似问题:

  某基类定义了一系列子类,如果要增加个新子类,源程序不用怎么改动,只需要添加新的子类就可以了,但是如何想增加新的操作(也就是函数),就需要改动所有相关类了。

  没看这本书之前觉得这个问题无解,看了这本书后发现可以轻松用 visitor 解决。

  其他的就是关于如何组织代码结构,以适应不断变动的需求。

  大家感兴趣的可以看看我每个章节的笔记:

  https://github.com/jiacai2050/ideas/issues/15

  :

  这本书国内买不到,amazon需要500多元,没办法只能找PDF了,但找了好久没清晰点的,只能凑合了,希望国内那个出版社能够引进这个书的翻译,造福国内的同胞们。

  《A Little Java, A Few Patterns》读后感(五):Notes

  Advantages of Java ------------------ - a small core language with a simple semantic model - gc Design Patterns --------------- Design patterns are used: - to organize your code - to communicate with others Introductory Language --------------------- Recommended introductory language: Scheme or ML. Too Much Coffee --------------- **Q:** Is it confusing that we need to connect `int` with `Integer` (e.g. `Integer(5)`) and `boolean` with `Boolean` (e.g. `Boolean(false)`)? **A:** Too much coffee does that. Note the book uses an early version of Java. Current Java can do auto boxing and unboxing for primitive types. Also, in this book, if the method specified its return type as `Object` in interface, then its implementation also annotated as returning `Object`, even when the implementation in fact always returns `Boolean`. **Q:** There is no number `x` in the world for which x = x + 1 So why should we expect there to be a Java `p` such that ```java p = new Top(new Anchovy(), p) ``` **A:** That's right. But that's what happens when you have one too many double espresso. Semicolon on Its Own Line for Mutability ---------------------------------------- ```java class PutSemicolonOnItsOwnLineForMutability { Pie p = new Crust(); Pie p = new Top(new Anchovy(), p) ; // the future begins, i.e. from this line on, references to `p` reflect the change Pieman yy = new Bottom(); yy.addTop(new Anchovy()) ; // same as above } ``` LittleJava.java --------------- ```java // `D` means this is a data class. abstract class Numᴰ {} class Zero extends Numᴰ {} class OneMoreThan extends Numᴰ { Numᴰ predecessor; // Constructor OneMoreThan(Numᴰ _p) { predecessor = _p; } } /* We did not tell you these are Peano axioms. We din not give formal definition. So you can form your own definition. Try to give it a name by yourself. This helps you to remember and understand it better. */

  /* This book shows how to protect direct access to property without the `private` access modifier. Wrap it into an interface. In that interface, only expose public methods, not the "private" property. */ /* Visitor pattern */ abstract class Shishᴰ { OnlyOnionsⱽ ooFn = new OnlyOnionsⱽ(); abstract boolean onlyOnions(); } class OnlyOnionsⱽ { boolean forSkewer() { return true; } boolean forOnion(Shishᴰ s) { return s.onlyOnions(); } boolean forLamb(Shishᴰ s) { return false; } boolean forTomato(Shishᴰ s) { return false; } } class Skewer extends Shishᴰ { boolean onlyOnions() { return ooFn.forSkewer(); } } class Onion extends Shishᴰ { Shishᴰ s; Onion(Shishᴰ _s) { s = _s; } boolean onlyOnions() { return ooFn.forOnion(s); } } class Lamb extends Shishᴰ { Shishᴰ s; Lamb(Shishᴰ _s) { s = _s; } boolean onlyOnions() { return ooFn.forLamb(s); } } class Tomato extends Shishᴰ { Shishᴰ s; Tomato(Shishᴰ _s) { s = _s; } boolean onlyOnions() { return ooFn.forTomato(s); } } /* Before introducing visitor pattern, every subclass of Shishᴰ need to contain the logic of `onlyOnions()` in its definition. And the book asked "Wasn't this overwhelming?" I had thought it would introduce generics next. But it turned out to be the visitor pattern. Oh, I forgot Java's generics are not reified. If Java had reified generics: class Shishᴰ { <S: Shishᴰ> boolean onlyOnions(S s) { if (s instanceof Sewer) { return false; } else if (s instanceof Onion) { return onlyOnions(s.s); } else { return false; } } } */

  /* This is for the loyal Schemers and MLers. */ interface Tᴵ { // It seems Java does not allow unicode arrows in identity name. // So we use the Chinese character `一` (one), which has a similar shape. o一oᴵ apply(Tᴵ x); } interface o一oᴵ { Object apply(Object x); } interface oo一ooᴵ { o一oᴵ apply(o一oᴵ x); } interface oo一oo一ooᴵ { o一oᴵ apply(oo一ooᴵ x); } class Y implements oo一oo一ooᴵ { public o一oᴵ apply(oo一ooᴵ f) { return new H(f).apply(new H(f)); } } class H implements Tᴵ { oo一ooᴵ f; H(oo一ooᴵ _f) { f = _f; } public o一oᴵ apply(Tᴵ x) { return f.apply(new G(x)); } } class G implements o一oᴵ { Tᴵ x; G(Tᴵ _x) { x = _x; } public Object apply(Object y) { return (x.apply(x)).apply(y); } } class MKFact implements oo一ooᴵ { public o一oᴵ apply(o一oᴵ fact) { return new Fact(fact); } } class Fact implements o一oᴵ { o一oᴵ fact; Fact(o一oᴵ _fact) { fact = _fact; } public Object apply(Object i) { int inti = ((Integer) i).intValue(); if (inti == 0) { return new Integer(1); } else { return new Integer( inti * ((Integer) fact.apply(new Integer(inti - 1))).intValue()); } } } // Try to figure out how the above code works. // First the concrete one `Fact`. // To construct a `Fact`, we need a `fact`. // Suppose we already have `fact`, then we call `fact.apply(n - 1)`. // To successfully continue the recursion, // `fact.apply(n - 1)` should be equivalent to something like `New Fact(...).apply(n - 1)`. // Oh! We need to construct a new `Fact`, which requires a `fact` again. // But wait. We already have `fact`, so we can reuse it. // That's it -- self reference. class Dummy implements o一oᴵ { public Object apply(Object x) { return new Fact(this).apply(x); } } // It works. // And it also what `MKFact.apply` needs. // // Let's move on. // `Fact` implements `o一oᴵ`, and `MKFact` implements `oo一ooᴵ`. // `o一oᴵ` is like a constructor, // and `oo一ooᴵ` is like a higher-order function taking a function and returning a function. // Similarly, `oo一oo一ooᴵ` is like a function taking a higher-order function that takes a function and returning a function. // Also `Tᴵ` is like a higher-order function returning a function. // // Now is the `Y`, `H`, `G` classes. // Our `Dummy` class works, but it makes `MKFact` redundant. // We need to find a way to produce `Fact` from `MKFact` without defining extra classes. // Let's look at the types. // `Fact` implements `o一oᴵ`, and `MKFact` implements `oo一ooᴵ`. // So we need something that takes `oo一ooᴵ` and returns `o一oᴵ`, a.k.a `oo一ooᴵ -> o一oᴵ`. // `Y.apply` happens to have such a signature. // Thus probably we can get a `Fact` through `new Y().apply(new MKFact())`? // And it works. // Why? // Revisit our `Dummy` class. // In `New Fact(new Dummy())`, `(new Dummy).apply` calls back `New Fact(this)`. // Next we demonstrate `new Y().apply(new MKFact())` is an equivalent form without `this`. // And by the definition of `Y`, `new Y().apply(new MKFact())` is `new MKFact().apply(new G(new H(new MKFact())))`. // Let `x = new G(new H(new MKFact()))`, we have `new MKFact().apply(x)`. // By the definition of `MKFact`, it is `new Fact(x)`. // Then we check what is `new Fact(x).apply(n)`. // Fill in the value of `x`, it is `new Fact(new G(new H(new MKFact())).apply(n)`. // By the definition of `Fact`, it is `new G(new H(new MKFact())).apply(n)`. // By the definition of `G`, it is `new H(new MKFact()).apply(new H(new MKFact())).apply(n)`. // By the definition of `H`, it is `new MKFact().apply(new G(new H(new MKFact()))).apply(n)`. // By the definition of `MKFact`, it is `new Fact(x).apply(n)`. // That is it. Self-referring to `Fact` itself without using `this`! // // This is the mighty Y combinator. // The scheme version is in The Little Schemer, chapter 9. // // Let's walk through the reinvention of it in Java. // // First let's write a straightforward recursion version of `fact`. class StaticFact { static int fact(int n) { if (n == 0) { return 1; } else { return n * fact(n - 1); } } } // Hmm, we haven't introduced static method in this book. // We did mention using static method like `Math.max` in footnotes, // but we never explain how to *declare* a static method. // Thus we changed it to a non static version. // The definition is almost the same. class NormalFact { int fact(int n) { if (n == 0) { return 1; } else { return n * fact(n - 1); } } } // We refer `fact` itself in function body, which is not possible in lambda calculus. // So we pass a function as parameter instead. // Oh, no! Java dose not support first class function. // Hmm, in fact we could pass a function via the reflection API, or as a lambda in Java 8. // But none of them is available when this book is written. // Thus we wrap the function in a class. // Note that we do not need a separate class. class Fact1 { int apply(Fact1 f, int n) { if (n == 0) { return 1; } else { return n * f.apply(f, n - 1); } } } // Nice! // But lambda can only accept one parameter. // We need to change `Fact1.apply` to return a function. // Again in Java we return a wrapped class instead. // To make future changes easier, // we declare an additional interface instead of using hard-coded class. interface Fact2ᴵ { int apply(int n); } class NClosure implements Fact2ᴵ { Fact2 f; NClosure(Fact2 _f) { f = _f; } public int apply(int n) { if (n == 0) { return 1; } else { return n * (f.apply(f)).apply(n - 1); } } } class Fact2 { Fact2ᴵ apply(Fact2 f) { return new NClosure(f); } } // This is the poor man's Y combinator. // Look at this line `return n * (f.apply(f)).apply(n - 1);`, // if it is `g.apply(n - 1)` then it would be similar to the original recursion version. // Let's `g = f.apply(f)`: class GG implements Fact2ᴵ { Fact3 f; GG(Fact3 _f) { f = _f; } public int apply(int n) { return (f.apply(f)).apply(n); } } class Fact3 { Fact2ᴵ apply(Fact3 f) { return new GClosure(f); } } class GClosure implements Fact2ᴵ { Fact3 f; GG g; GClosure(Fact3 _f) { f = _f; g = new GG(f); } public int apply(int n) { if (n == 0) { return 1; } else { return n * g.apply(n - 1); } } } // We are almost done. // `GClosure.apply()` is the recursion definition we want. // Let's create something that takes a `GClosure`. class YY { Fact2ᴵ f; YY(Fact2ᴵ _f) { f = _f; } int apply(int n) { return f.apply(n); } } // Hmm, the problem is we still need `Fact3`, whose definition hard coded reference to `GClosure`. // We could made the constructor of `Fact3` taking `GClosure` as a parameter. // That is, to construct a `Fact3`, we need a `GClosure`, // and to construct a `GClosure`, we need a `Fact3`. // Now if we make `Fact3` and `GClosure` one thing, it will be self-referral. class Fact0 implements Fact2ᴵ { Fact2ᴵ g; Fact0(Fact2ᴵ _g) { g = _g; } public int apply(int n) { if (n == 0) { return 1; } else { return n * g.apply(n - 1); } } } // Now the tricky part is constructing `Fact0(_f)`. // Again this smells like self-reference. // Just as we introduced an additional function as parameter before, // to construct `Fact0(_f)` we probably need an additional function. class MKFact0 { Fact2ᴵ apply(Fact2ᴵ fact2ᴵ) { return new Fact0(fact2ᴵ); } } // Now we need to define `Y0` such that `new Y0().apply(new MKFact0())` will construct a `Fact0`. // It is hard to write the `apply` method of `Y0`. // Let's go back to last iteration. // `GG` is not abstract. It has `Fact3` hard coded in its definition. // Let's refactor it. class G0 implements Fact2ᴵ { Fact2ᴵ g; G0(Fact2ᴵ _g) { g = _g; } public int apply(int n) { return (g.apply(g)).apply(n); } } // Oops! `g.apply(g)` is invalid. // From here we may try to rewrite `G0`. // Or we may try to rewrite `Fact2ᴵ`, `int -> int` is too restrictive, // i.e. if we cannot solve a specific problem, // try to solve its more general form. // Rewrite `Fact2ᴵ`, substitute `int` with `Object`, we get `o一oᴵ`. // Change `Fact0` and `MKFact0` accordingly, we get `Fact` and `MKFact`. // `Fact` implements `o一oᴵ`, we need to define an interface for `MKFact` as well. That is `oo一ooᴵ`. // Now we try to rewrite `G0`. // We find that `g.apply(g)` still cause type mismatch. // `g` cannot be an ordinary `Object`, which may no have an `apply` method defined. // Also `g` cannot be an `o一oᴵ`, which cannot take itself (`o一oᴵ`) as a parameter. // Thus we need a new type (interface). // An interface whose `apply` method takes anything (an `Object`) and returns an `o一oᴵ`. // Thus we have `Tᴵ`. // Then we look at `Y`. // We still dose not know how to write its `apply` method, but we know the signature of it. // It takes `MKFact`, a.k.a. `oo一ooᴵ`, and returns `Fact`, a.k.a. `o一oᴵ`. // Thus we have `oo一oo一ooᴵ`. // // We try to pass `MKFact` to `G`, `new G(new MKFact())`. // Not possible. We need a bridge to connect `oo一ooᴵ` and `Tᴵ`, // i.e. something takes a `MKFact` a.k.a. `oo一ooᴵ` and produces a `Tᴵ` for `G`. class H implements Tᴵ { oo一ooᴵ f; H(oo一ooᴵ _f) { f = _f; } public o一oᴵ apply(Tᴵ x) { return ...; } } // Now we need to fill in the missing `apply` definition for `H`. // It returns `o一oᴵ`. Do we have something returns `o一oᴵ`? // `f.apply` happens to produce `o一oᴵ`. class H implements Tᴵ { oo一ooᴵ f; H(oo一ooᴵ _f) { f = _f; } public o一oᴵ apply(Tᴵ x) { return f.apply(...); } } // `f.apply()` takes an `o一oᴵ`. Do we have something to transform `Tᴵ` to `o一oᴵ`? // The `apply` method of `Tᴵ`. // Do we have some class implements `Tᴵ`, except `H` itself? // No. // So we need to implement one? // Wait. `G` implements `o一oᴵ` and its construction method takes `Tᴵ` as parameter. // So `new G(x)` fills in the gap. class H implements Tᴵ { oo一ooᴵ f; H(oo一ooᴵ _f) { f = _f; } public o一oᴵ apply(Tᴵ x) { return f.apply(new G(x)); } } // In fact, this is the very definition given in the book. // // At last, let's complete `Y`. class Y implements oo一oo一ooᴵ { public o一oᴵ apply(oo一ooᴵ f) { return ...; } } // We need something takes `oo一ooᴵ` and produces `o一oᴵ`. // `H` takes `oo一ooᴵ` in its construction method, and produces `o一oᴵ` by its `apply` method. class Y implements oo一oo一ooᴵ { public o一oᴵ apply(oo一ooᴵ f) { return new H(f).apply(...); } } // The parameter of `H(f).apply()` need to be a `Tᴵ`. // Do we have something implements `Tᴵ`? // `H` itself. // So class Y implements oo一oo一ooᴵ { public o一oᴵ apply(oo一ooᴵ f) { return new H(f).apply(new H(f)); } } // The very definition given in the book. // If you still have difficulties to understand it in Java, // try use another language. // For example, // // ```js // // Poor man's Y combinator // ((f => n => n == 0 ? 1 : n * f(f)(n - 1)) // (f => n => n == 0 ? 1 : 0 * f(f)(n - 1)) // 3) // ``` // // It would be perfect if it is `f(n -1)` instead of `f(f(n)(n - 1))`. // Let `g = f(f)`: // // ```js // ((f => ((g => n => n == 0 ? 1 : n * g(n - 1)) f(f)) // # same as above // 3) // ``` // // Hmm, `(g => n => n == 0 ? 1 : n * g(n - 1)` is just what we want! // Let `h = (g => n => n == 0 ? 1 : n * g(n - 1)`: // // ```js // (((h => // (f => h(f(f))) // (f => h(f(f)))) // (g => n => n == 0 ? 1 : n * g(n - 1)) // 3) // ``` // // Look! The factorial logic is factor out: `(g => n => n == 0 ? 1 : n * g(n - 1))`. // And this is the Y combinator. // // ```js // Y = // (h => // (f => h(f(f))) // (f => h(f(f)))) // ``` // // To construct `fact` with Y combinator: `Y(g => n => n == 0 ? 1 : n * g(n - 1))`. // // Hope this helps to understand those `Y`, `H`, `G` classes in Java. public class LittleJava { public static void main(String[] args) { Fact fact = new Fact(new Dummy()); System.out.println(fact.apply(new Integer(5))); MKFact mKFact = new MKFact(); Fact newFact = (Fact) mKFact.apply(new Dummy()); System.out.println(newFact.apply(new Integer(5))); Fact yFact = (Fact) new Y().apply(new MKFact()); System.out.println(yFact.apply(new Integer(5))); System.out.println("static recursion version"); System.out.println(StaticFact.fact(5)); System.out.println("normal version"); NormalFact normalFact = new NormalFact(); System.out.println(normalFact.fact(5)); System.out.println("Fact1"); Fact1 fact1 = new Fact1(); System.out.println(fact1.apply(fact1, 5)); System.out.println("Fact2: poor man's Y combinator"); Fact2 fact2 = new Fact2(); System.out.println((fact2.apply(fact2)).apply(5)); System.out.println("Fact3: g = f(f)"); Fact3 fact3 = new Fact3(); System.out.println((fact3.apply(fact3)).apply(5)); System.out.println("YY"); YY yy = new YY(new GClosure(new Fact3())); System.out.println(yy.apply(5)); } } ```

  https://weakish.github.io/StutteringTalkaholic/java/a-little/

评价:

[匿名评论]登录注册

评论加载中……