代理模式
// : typeinf0/SimpleProxyDemo.j ava import static net.mindview.util.Print.*; interface Interface { void doSomething(); void somethingElse(String arg); } class RealObject implements Interface { public void doSomething() { print("doSomething"); } public void somethingElse(String arg) { print("somethingElse " + arg); } } class SimpleProxy implements Interface { private Interface proxied; public SimpleProxy(Interface proxied) { this.proxied = proxied; } public void doSomething() { print("SimpleProxy doSomething"); proxied.doSomething(); } public void somethingElse(String arg) { print("SimpleProxy somethingElse " + arg); proxied.somethingElse(arg); } } public class SimpleProxyDemo { public static void consumer(Interface iface) { iface.doSomething(); iface.somethingElse("bonobo"); } public static void main(String[] args) { consumer(new RealObject()); consumer(new SimpleProxy(new RealObject())); } }
动态代理模式
// : typeinfo/SimpleDynamicProxy.java import java.lang.reflect.*; class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler(Object proxied) { this.proxied = proxied; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args); if (args != null) for (Object arg : args) System.out.println(" " + arg); return method.invoke(proxied, args); } } public class SimpleDynamicProxy { public static void consumer(Interface iface) { iface.doSomething(); iface.somethingElse("bonobo"); } public static void main(String[] args) { RealObject real = new RealObject(); consumer(real); // Insert a proxy and call again: Interface proxy = (Interface) Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[] { Interface.class }, new DynamicProxyHandler(real)); consumer(proxy); } }
//: typeinfo/SelectingMethods.java // Looking for particular methods in a dynamic proxy. import java.lang.reflect.*; import static net.mindview.util.Print.*; class MethodSelector implements InvocationHandler { private Object proxied; public MethodSelector(Object proxied) { this.proxied = proxied; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("interesting")) print("Proxy detected the interesting method"); return method.invoke(proxied, args); } } interface SomeMethods { void boringl(); void boring2(); void interesting(String arg); void boring3(); } class Implementation implements SomeMethods { public void boringl() { print("boringl"); } public void boring2() { print("boring2"); } public void interesting(String arg) { print("interesting " + arg); } public void boring3() { print("boring3"); } } public class SelectingMethods { public static void main(String[] args) { SomeMethods proxy = (SomeMethods) Proxy.newProxyInstance( SomeMethods.class.getClassLoader(), new Class[] { SomeMethods.class }, new MethodSelector( new Implementation())); proxy.boringl(); proxy.boring2(); proxy.interesting("bonobo"); proxy.boring3(); } }
Strategy pattern
a special case of the Strategy pattern
Null Objects
The problem is that null has no behavior of its own except for producing a NullPointerException if you try to do anything with it. Sometimes it is useful to introduce the idea of a Null Objects that will accept messages for the object that it's "standing in" for, but will return values indicating that no "real" object is actually there. This way, you can assume that all objects are valid and you don't have to waste programming time checking for null (and reading the resulting code).
Although it's fun to imagine a programming language that would automatically create Null Objects for you(Object C就是这样的), in practice it doesn't make sense to use them everywhere—sometimes checking for null is fine, and sometimes you can reasonably assume that you won't encounter null, and sometimes even detecting aberrations via NullPointerException is acceptable. The place where Null Objects seem to be most useful is "closer to the data," with objects that represent entities in the problem space. As a simple example,many systems will have a Person class, and there are situations in the code
where you don't have an actual person (or you do, but you don't have all the information about that person yet), so traditionally you'd use a null reference and test for it. Instead, we can make a Null Object. But even though the Null Object will respond to all messages that the "real" object will respond to, you still need a way to test for nullness. The simplest way to do this is to create a tagging interface:
// : net/mindview/uti1/Null.java package net.mindview.util ; public interface Null { }
This allows instanceof to detect the Null Object, and more importantly,does not require you to add an isNull( ) method to all your classes (which would be, after all, just a different way of performing RTTI—why not use the built-in facility instead?).
//: typeinfo/Person.java // A class with a Null Object. import net.mindview.util.*; class Person { public final String first; public final String last; public final String address; // etc. public Person(String first, String last, String address) { this.first = first; this.last = last; this.address = address; } public String toString() { return "Person: " + first + " " + last + " " + address; } public static class NullPerson extends Person implements Null { private NullPerson() { super("None", "None", "None"); } public String toString() { return "NullPerson"; } } public static final Person NULL = new NullPerson(); } // /:-
In general, the Null Object will be a Singleton, so here it is created as a static final instance. This works because Person is immutable—you can only set the values in the constructor, and then read those values, but you can't modify them (because Strings themselves are inherently immutable). If you want to change a NullPerson, you can only replace it with a new Person object. Notice that you have the option of detecting the generic Null or the more specific NullPerson using instanceof, but with the Singleton approach you can also just use equals( ) or even == to compare to Person.NULL.
Now suppose you're back in the high-flying days of Internet startups and you've been given a big pile of venture funding for your Amazing Idea. You'r ready to staff up, but while you're waiting for positions to be filled, you can use Person Null Objects as placeholders for each Position:
//: typeinfo/Position.java public class Position { private String title; private Person person; public Position(String jobTitle, Person employee) { title = jobTitle; person = employee; if (person == null) person = Person.NULL; } public Position(String jobTitle) { title = jobTitle; person = Person.NULL; } public String getTitle() { return title; } public void setTitle(String newTitle) { title = newTitle; } public Person getPerson() { return person; } public void setPerson(Person newPerson) { person = newPerson; if (person == null) person = Person.NULL; } public String toString() { return "Position: " + title + " " + person; } } // /:-
With Position, we don't need to make a Null Object because the existence of Person.NULL implies a null Position (it's possible that, later, you'll discover the need to add an explicit Null Object for Position, but YAGNI(You Aren't Going to Need It) says to try "the simplest thing that could possibly work" for your first draft, and to wait until some aspect of the program requires you to add in the extra feature, rather than assuming it's necessary).
The Staff class can now look for Null Objects when you are filling positions:
// : typeinfo/Staff.java import java.util.*; public class Staff extends ArrayList<Position> { public void add(String title, Person person) { add(new Position(title, person)); } public void add(String... titles) { for (String title : titles) add(new Position(title)); } public Staff(String... titles) { add(titles); } public boolean positionAvailable(String title) { for (Position position : this) if (position.getTitle().equals(title) && position.getPerson() == Person.NULL) return true; return false; } public void fillPosition(String title, Person hire) { for (Position position : this) if (position.getTitle().equals(title) && position.getPerson() == Person.NULL) { position.setPerson(hire); return; } throw new RuntimeException("Position " + title + " not available"); } public static void main(String[] args) { Staff staff = new Staff("President", "CTO", "Marketing Manager", "Product Manager", "Project Lead", "Software Engineer", "Software Engineer", "Software Engineer", "Software Engineer", "Test Engineer", "Technical Writer"); staff.fillPosition("President", new Person("Me", "Last", "The Top, Lonely At")); staff.fillPosition("Project Lead", new Person("Janet", "Planner", "The Burbs")); if (staff.positionAvailable("Software Engineer")) staff.fillPosition("Software Engineer", new Person("Bob", "Coder", "Bright Light City")); System.out.println(staff); } }
Notice that you must still test for Null Objects in some places, which is not that different from checking for null, but in other places (such as toString( ) conversions, in this case), you don't have to perform extra tests;you can just assume that all object references are valid.
If you are working with interfaces instead of concrete classes, it's possible to use a DynamicProxy to automatically create the Null Objects. Suppose we have a Robot interface that defines a name, model, and a List < Operation > that describes what the Robot is capable of doing. Operation contains a description and a command (it's a type of Command pattern):
//: typeinfo/Operation.Java public interface Operation { String description(); void command(); } // /:-
You can access a Robot's services by calling operations( ):
// : typeinfo/Robot.java import java.util.*; import net.mindview.util.*; public interface Robot { String name(); String model(); List<Operation> operations(); class Test { public static void test(Robot r) { if (r instanceof Null) System.out.println(" [Null Robot] "); System.out.println("Robot name: " + r.name()); System.out.println("Robot model: " + r.model()); for (Operation operation : r.operations()) { System.out.println(operation.description()); operation.command(); } } } } // /:-
This also incorporates a nested class to perform tests.
We can now create a Robot that removes snow:
// : typeinfo/SnowRemovalRobot.Java import java.util.*; public class SnowRemovalRobot implements Robot { private String name; public SnowRemovalRobot(String name) { this.name = name; } public String name() { return name; } public String model() { return "SnowBot Series 11"; } public List<Operation> operations() { return Arrays.asList(new Operation() { public String description() { return name + " can shovel snow"; } public void command() { System.out.println(name + " shoveling snow"); } }, new Operation() { public String description() { return name + " can chip ice"; } public void command() { System.out.println(name + " chipping ice"); } }, new Operation() { public String description() { return name + " can clear the roof"; } public void command() { System.out.println(name + " clearing roof"); } }); } public static void main(String[] args) { Robot.Test.test(new SnowRemovalRobot("Slusher")); } }There will presumably be many different types of Robot, and we'd like to have each Null Object do something special for each Robot type—in this case, incorporate information about the exact type of Robot the Null Object is standing for. This information will be captured by the dynamic proxy:
相关推荐
Thinking in Java 课文中的代码
Thinking in java java源代码,书中所有裤和例子,必备
英文版Thinking in java Thinking in Java Fourth Edition Bruce Eckel President, MindView, Inc.
Thinking in Java 3rd Edition,这次该书第三版的所有源代码
Thinking in java 4th 源代码
thinking injava 中英文完整版
Thinking in Java 习题答案, 源代码
Thinking in Java 4th Edition Annotated Solutions Guide!
浙江大学 翁凯java语言视频中ppt thinking in java 源代码
thinking in java代码,想要的来下载吧,对学习教材很有用
Thinking in Java 4Edition 练习题答案
Thinking in java 电子书,经典java书籍
Thinking in java中文txt格式的,下到手机看吧
Thinking in Java(java编程思想) 第三版+第四版(完整中文版电子书+配套习题答案) 本资料包括四部分内容: 1、Thinking in Java 3th Edition.pdf为java编程思想第三版,是中文版,pdf格式,不是扫描版,非常清晰...
thinking in java 4最新版本,中文高清pdf,同时附带书中源代码,绝对真实
thinking in java thinking in java thinking in java thinking in java thinking in java
Thinking in Java 4th Edition 英文文字版,带书签 Annotated Solution Guide 有代码
thinking in java 文档
thinking in java第4版开发源码,从别处转载,方便大家下载
Thinking In Java-Java 编程思想(中英文版 第四版) Thinking In Java-Java 编程思想(中英文版 第四版)