聚合(aggregation):聚合是关联的一种特殊形式,表示一件事物是由另一件事物(部分地)组成。
在Java中的称呼:抽象类(abstract class),关系(relationship),继承(inheritance),聚合(aggregation)
在UML中的称呼:抽象类(abstract class),关联(association),泛化(generalization),聚合(aggregation)
OO原则:
1.将变化之物封装起来
2.对接口编码,而不是对实现
3.应用程序中的每一个类只有一个改变的理由
灵活性(flexible),复原力(resilient),耦合度(coupling),内聚力(cohesion)
大多数的好设计都是通过分析坏设计而来的。
不要害怕犯错和改变。
还记得吉他店老板吗(可以看第一章和第二章)?他用我们做的吉他搜索工具,吉他大卖。但是,现在他有了新的需求:
店长说我不想只买吉他,我想增加更多的乐器种类:比如像曼陀林(mandolin)等
回看我们的代码,
项目架构:
Builder.java:
1 package com.headfirst.guitar; 2 3 public enum Builder { 4 5 FENDER, MARTIN, GIBSON, COLLINGS, OLSON, RYAN, PRS, ANY; 6 7 public String toString(){ 8 switch(this){ 9 case FENDER: 10 return "Fender"; 11 case MARTIN: 12 return "Martin"; 13 case GIBSON: 14 return "Gibson"; 15 case COLLINGS: 16 return "Collings"; 17 case OLSON: 18 return "Olson"; 19 case RYAN: 20 return "Ryan"; 21 case PRS: 22 return "Prs"; 23 case ANY: 24 return "Any"; 25 default: 26 return ""; 27 } 28 } 29 }
Type.java:
1 package com.headfirst.guitar; 2 3 public enum Type { 4 ACOUSTIC, ELECTRIC; 5 6 public String toString(){ 7 switch(this){ 8 case ACOUSTIC: 9 return "acoustic"; 10 case ELECTRIC: 11 return "electric"; 12 default: 13 return ""; 14 } 15 } 16 }
Wood.java:
1 package com.headfirst.guitar; 2 3 public enum Wood { 4 INDIAN_ROSEWOOD, BRAZILIAN_ROSEWOOD, ALDER; 5 6 public String toString(){ 7 switch(this){ 8 case INDIAN_ROSEWOOD: 9 return "Indian Rosewood"; 10 case BRAZILIAN_ROSEWOOD: 11 return "Brazilian Rosewood"; 12 case ALDER: 13 return "Alder"; 14 default: 15 return ""; 16 } 17 } 18 }
Guitar.java:
1 package com.headfirst.guitar; 2 3 public class Guitar { 4 private String serialNumber; 5 private double price; 6 private GuitarSpec guitarSpec; 7 8 public Guitar(String serialNumber, double price, GuitarSpec guitarSpec){ 9 this.serialNumber = serialNumber; 10 this.price = price; 11 this.guitarSpec = guitarSpec; 12 } 13 14 public String getSerialNumber(){ 15 return serialNumber; 16 } 17 public double getPrice(){ 18 return price; 19 } 20 public void setPrice(float newPrice){ 21 this.price = newPrice; 22 } 23 public GuitarSpec getGuitarSpec(){ 24 return guitarSpec; 25 } 26 }
GuitarSpec.java:
1 package com.headfirst.guitar; 2 3 public class GuitarSpec { 4 Builder builder; 5 String model; 6 Type type; 7 Wood backWood; 8 Wood topWood; 9 int numStrings; 10 11 12 public GuitarSpec(Builder builder, String model, Type type, Wood backWood, Wood topWood){ 13 this.builder = builder; 14 this.model = model; 15 this.type = type; 16 this.backWood = backWood; 17 this.topWood = topWood; 18 this.numStrings = numStrings; 19 } 20 21 public Builder getBuilder(){ 22 return this.builder; 23 } 24 25 public String getModel(){ 26 return this.model; 27 } 28 29 public Type getType(){ 30 return this.type; 31 } 32 33 public Wood getBackWood(){ 34 return this.backWood; 35 } 36 37 public Wood getTopWood(){ 38 return this.topWood; 39 } 40 41 public int getNumStrings(){ 42 return this.numStrings; 43 } 44 45 public boolean matches(GuitarSpec otherSpec){ 46 if(builder != otherSpec.builder) 47 return false; 48 if((model != null) && (!model.equals("")) && 49 (!model.equalsIgnoreCase(otherSpec.model))) 50 return false; 51 if(type != otherSpec.type) 52 return false; 53 if(numStrings != otherSpec.numStrings) 54 return false; 55 if(backWood != otherSpec.backWood) 56 return false; 57 if(topWood != otherSpec.topWood) 58 return false; 59 60 return true; 61 } 62 }
Inventory.java:
1 package com.headfirst.guitar; 2 3 import java.util.Iterator; 4 import java.util.LinkedList; 5 import java.util.List; 6 7 public class Inventory { 8 9 private List guitars; 10 11 public Inventory(){ 12 guitars = new LinkedList(); 13 } 14 15 public void addGuitar(String serialNumber, double price, GuitarSpec guitarSpec){ 16 Guitar guitar = new Guitar(serialNumber, price, guitarSpec); 17 guitars.add(guitar); 18 } 19 20 public Guitar getGuitar(String serialNumber){ 21 for(Iterator i = guitars.iterator(); i.hasNext();){ 22 Guitar guitar = (Guitar) i.next(); 23 if(guitar.getSerialNumber().equals(serialNumber)){ 24 return guitar; 25 } 26 } 27 28 return null; 29 } 30 31 public List search(GuitarSpec searchGuitar){ 32 List matchingGuitars = new LinkedList(); 33 for(Iterator i = guitars.iterator(); i.hasNext();){ 34 Guitar guitar = (Guitar) i.next(); 35 if(guitar.getGuitarSpec().matches(searchGuitar)) 36 matchingGuitars.add(guitar); 37 } 38 39 return matchingGuitars; 40 } 41 }
FindGuitarTester.java:
1 package com.headfirst.guitar; 2 3 import java.util.Iterator; 4 import java.util.List; 5 6 public class FindGuitarTester { 7 public static void main(String[] args){ 8 Inventory inventory = new Inventory(); 9 initializeInventory(inventory); 10 11 GuitarSpec whatErinLikes = new GuitarSpec(Builder.FENDER, "Stratocastor", Type.ELECTRIC, Wood.ALDER, Wood.ALDER); 12 13 List matchingGuitars = inventory.search(whatErinLikes); 14 if(!matchingGuitars.isEmpty()){ 15 System.out.println("Erin, you might like these guitars: "); 16 for(Iterator i = matchingGuitars.iterator(); i.hasNext();){ 17 Guitar guitar = (Guitar) i.next(); 18 GuitarSpec guitarSpec = guitar.getGuitarSpec(); 19 System.out.println("We have a " + 20 guitarSpec.getBuilder() + " " + guitarSpec.getModel() + " " + 21 guitarSpec.getType() + " guitar: " + 22 guitarSpec.getBackWood() + " back and sides, " + 23 guitarSpec.getTopWood() + " top. You can have it for only $" + 24 guitar.getPrice() + "!"); 25 } 26 }else{ 27 System.out.println("Sorry, Erin, we have nothing for you."); 28 } 29 } 30 31 private static void initializeInventory(Inventory inventory){ 32 GuitarSpec guitarSpec1 = new GuitarSpec(Builder.FENDER, "Stratocastor", Type.ELECTRIC, Wood.ALDER, Wood.ALDER); 33 inventory.addGuitar("V95693", 1499.95, guitarSpec1); 34 inventory.addGuitar("B1234", 1600.35, guitarSpec1); 35 } 36 }
上面代码,如果有什么疑问,可以指出。
根据吉他店长,不,应该叫乐器店长,的指示。我们来扩展和修改我们上面的代码,看有什么问题?
我们只有一个Guitar类,想要Mandolin类,再创建一个吧。想到两者似乎有些相同的地方,可以我们抽象出Instrument类怎么样,让新增的乐器都继承它。
太棒了!GuitarSpec类也一样,我们抽象出InstrumentSpec类,让新增的乐器属性都继承自它。
这是我们构建出的新的UML类图。
根据上图写代码:
新建项目:
你可以像我一样新建一个项目,也可以在原有项目基础上更改。
Builder.java:
1 package com.headfirst.instrument; 2 3 public enum Builder { 4 FENDER, MARTIN, GIBSON, COLLINGS, OLSON, RYAN, PRS, ANY; 5 6 public String toString(){ 7 switch(this){ 8 case FENDER: 9 return "Fender"; 10 case MARTIN: 11 return "Martin"; 12 case GIBSON: 13 return "Gibson"; 14 case COLLINGS: 15 return "Collings"; 16 case OLSON: 17 return "Olson"; 18 case RYAN: 19 return "Ryan"; 20 case PRS: 21 return "Prs"; 22 case ANY: 23 return "Any"; 24 default: 25 return ""; 26 } 27 } 28 }
Style.java:
1 package com.headfirst.instrument; 2 3 public enum Style { 4 A, F; 5 6 public String toString(){ 7 switch(this){ 8 case A: 9 return "a"; 10 case F: 11 return "F"; 12 default: 13 return "kong"; 14 } 15 } 16 }
Type.java:
1 package com.headfirst.instrument; 2 3 public enum Type { 4 ACOUSTIC, ELECTRIC; 5 6 public String toString(){ 7 switch(this){ 8 case ACOUSTIC: 9 return "acoustic"; 10 case ELECTRIC: 11 return "electric"; 12 default: 13 return ""; 14 } 15 } 16 }
Wood.java:
1 package com.headfirst.instrument; 2 3 public enum Wood { 4 INDIAN_ROSEWOOD, BRAZILIAN_ROSEWOOD, ALDER; 5 6 public String toString(){ 7 switch(this){ 8 case INDIAN_ROSEWOOD: 9 return "Indian Rosewood"; 10 case BRAZILIAN_ROSEWOOD: 11 return "Brazilian Rosewood"; 12 case ALDER: 13 return "Alder"; 14 default: 15 return ""; 16 } 17 } 18 }
Instrument.java:
1 package com.headfirst.instrument; 2 3 public abstract class Instrument { 4 5 private String serialNumber; 6 private double price; 7 private InstrumentSpec spec; 8 9 public Instrument(String serialNumber, double price, InstrumentSpec spec){ 10 this.serialNumber = serialNumber; 11 this.price = price; 12 this.spec = spec; 13 } 14 15 public String getSerialNumber(){ 16 return serialNumber; 17 } 18 public double getPrice(){ 19 return price; 20 } 21 public void setPrice(){ 22 this.price = price; 23 } 24 25 public InstrumentSpec getSpec(){ 26 return spec; 27 } 28 }
InstrumentSpec.java:
1 package com.headfirst.instrument; 2 3 4 public abstract class InstrumentSpec { 5 6 private Builder builder; 7 private String model; 8 private Type type; 9 private Wood backWood; 10 private Wood topWood; 11 12 public InstrumentSpec(Builder builder, String model, Type type, Wood backWood, Wood topWood){ 13 this.builder = builder; 14 this.model = model; 15 this.type = type; 16 this.backWood = backWood; 17 this.topWood = topWood; 18 } 19 20 public Builder getBuilder(){ 21 return this.builder; 22 } 23 24 public String getModel(){ 25 return this.model; 26 } 27 28 public Type getType(){ 29 return this.type; 30 } 31 32 public Wood getBackWood(){ 33 return this.backWood; 34 } 35 36 public Wood getTopWood(){ 37 return this.topWood; 38 } 39 40 public boolean matches(InstrumentSpec otherSpec){ 41 if(builder != otherSpec.builder) 42 return false; 43 if((model != null) && (!model.equals("")) && (!model.equalsIgnoreCase(otherSpec.model))) 44 return false; 45 if(type != otherSpec.type) 46 return false; 47 if(backWood != otherSpec.backWood) 48 return false; 49 if(topWood != otherSpec.topWood) 50 return false; 51 52 return true; 53 } 54 }
Guitar.java:
1 package com.headfirst.instrument; 2 3 public class Guitar extends Instrument { 4 5 public Guitar(String serialNumber, double price, GuitarSpec spec){ 6 super(serialNumber, price, spec); 7 } 8 }
GuitarSpec.java:
1 package com.headfirst.instrument; 2 3 public class GuitarSpec extends InstrumentSpec { 4 private int numStrings;//Guitar自身属性 5 6 public GuitarSpec(Builder builder, String model, Type type, Wood backWood, Wood topWood, int numStrings){ 7 super(builder, model, type, backWood, topWood); 8 9 this.numStrings = numStrings; 10 } 11 12 public int getNumStrings(){ 13 return numStrings; 14 } 15 16 //Override the superclass matches() 17 public boolean matches(InstrumentSpec otherSpec){ 18 if(!super.matches(otherSpec)){ 19 return false; 20 } 21 if(!(otherSpec instanceof GuitarSpec)) 22 return false; 23 GuitarSpec spec = (GuitarSpec) otherSpec; 24 if( numStrings != spec.numStrings) 25 return false; 26 27 return true; 28 } 29 }
Mandolin.java:
1 package com.headfirst.instrument; 2 3 public class Mandolin extends Instrument { 4 5 public Mandolin(String serialNumber, double price, MandolinSpec spec){ 6 super(serialNumber, price, spec); 7 } 8 }
MandolinSpec.java:
1 package com.headfirst.instrument; 2 3 public class MandolinSpec extends InstrumentSpec { 4 private Style style; 5 6 public MandolinSpec(Builder builder, String model, Type type, Wood backWood, Wood topWood, Style style){ 7 super(builder, model, type, backWood, topWood); 8 9 this.style = style; 10 } 11 12 public Style getStyle(){ 13 return style; 14 } 15 //Override the superclass matches() 16 public boolean matches(InstrumentSpec otherSpec){ 17 if(!(super.matches(otherSpec))) 18 return false; 19 if(!(otherSpec instanceof MandolinSpec)) 20 return false; 21 MandolinSpec spec = (MandolinSpec) otherSpec; 22 if(!style.equals(spec.style)) 23 return false; 24 25 return true; 26 } 27 }
Inventory.java:
1 package com.headfirst.instrument; 2 3 import java.util.Iterator; 4 import java.util.LinkedList; 5 import java.util.List; 6 7 public class Inventory { 8 9 private List inventory; 10 11 public Inventory(){ 12 inventory = new LinkedList(); 13 } 14 15 public void addInstrument(String serialNumber, double price, InstrumentSpec spec){ 16 Instrument instrument = null; 17 if(spec instanceof GuitarSpec){ 18 instrument = new Guitar(serialNumber, price, (GuitarSpec) spec); 19 }else if(spec instanceof MandolinSpec){ 20 instrument = new Mandolin(serialNumber, price, (MandolinSpec) spec); 21 } 22 23 inventory.add(instrument); 24 } 25 26 public Instrument get(String serialNumber){ 27 for(Iterator i = inventory.iterator(); i.hasNext();){ 28 Instrument instrument = (Instrument) i.next(); 29 if(instrument.getSerialNumber().equals(serialNumber)){ 30 return instrument; 31 } 32 } 33 34 return null; 35 } 36 37 public List search(GuitarSpec searchSpec){ 38 List matchingGuitars = new LinkedList(); 39 for(Iterator i = inventory.iterator(); i.hasNext();){ 40 Guitar guitar = (Guitar) i.next(); 41 if(guitar.getSpec().matches(searchSpec)) 42 matchingGuitars.add(guitar); 43 } 44 45 return matchingGuitars; 46 } 47 48 public List search(MandolinSpec searchSpec){ 49 List matchingMandolins = new LinkedList(); 50 for(Iterator i = inventory.iterator(); i.hasNext();){ 51 Mandolin mandolin = (Mandolin) i.next(); 52 if(mandolin.getSpec().matches(searchSpec)) 53 matchingMandolins.add(mandolin); 54 } 55 56 return matchingMandolins; 57 } 58 }
没有写FindInstrumentTester.java,因为这个项目有个问题,很难扩展。
不信?我说,你来修改一下,现在我们要增加乐器:古筝,短笛,箫,二胡......;一共一百种,而且每种乐器带有自身的特殊属性,不多每种就带一种吧。
是不是代码写到你手酸?不是,好吧,那你一定为你的复制粘贴而沾沾自喜。
下面我们对上面Instrument项目进行修改,怎样在增加很多乐器的时候,我们的代码改动性很小。
来说几个OO原则:
1.接口(interface):对接口编程,而不是对实现编程,软件更容易被扩展。通过接口编程,程序代码将使用该接口的所有子类,甚至是没被创建的那些。
2.封装(encapsulation):将变化之物封装起来,将不变之物也封装起来。通过封装你改动的代码将在封装之内,对于封装之外的代码,你不必担心。
3.变更(change):每个类只有一个改变的理由。减少引起该类变动的因素,就可以让此类发生变动的机会最小化。每个类只做一件事。
说一说,项目扩展的难处在哪里吧:
首先,要通过继承Instrument类,写出很多实现乐器类,通过继承InstrumentSpec类,写出很多实现乐器属性类
其次,乐器有不同的特殊属性,要在乐器属性类中添加上,在对比matches方法中也要对比这些特殊属性
最后,在Inventory类中,search方法要根据多少种乐器,写出多少种搜索方法
这些问题所在,就是我们继承了Instrument抽象类和InstrumentSpec抽象类,因为抽象类不能实例化,导致有多少乐器就要写多少。
有没有办法,把所有的乐器都用一个Instrument类表示?这样我们就不用写太多的子类了,我们只在乐器属性中中添加一个instrumentType变量来存储乐器的种类
如果这样,那些乐器特有的属性怎样表示?不可能所有乐器的属性都相同吧。
有没有想过封装,我们把乐器的属性在进一步封装起来,但我们不把属性封装到类中,而是封装在Map中,一个属性一个键值对。InstrumentSpec中存储Map。想要哪个属性就去里面取值就好了。
搜索方法写太多,没关系,我们也把InstrumentSpec也只用一个表示,怎么样?
说了这么多,具体怎么实现,是还不明白。那么就让我执笔敲出上述代码:
项目架构:
枚举多了一个InstrumentType,用来存储乐器种类,其余的枚举有的里面增加了一些内容:
Builder.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public enum Builder { 4 FENDER, MARTIN, GIBSON, COLLINGS, OLSON, RYAN, PRS, ANY; 5 6 public String toString(){ 7 switch(this){ 8 case FENDER: 9 return "Fender"; 10 case MARTIN: 11 return "Martin"; 12 case GIBSON: 13 return "Gibson"; 14 case COLLINGS: 15 return "Collings"; 16 case OLSON: 17 return "Olson"; 18 case RYAN: 19 return "Ryan"; 20 case PRS: 21 return "Prs"; 22 case ANY: 23 return "Any"; 24 default: 25 return ""; 26 } 27 } 28 }
InstrumentType.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public enum InstrumentType { 4 GUITAR, BANJO, DOBRO, FIDDLE, BASS, MANDOLIN; 5 6 public String toString(){ 7 switch(this){ 8 case GUITAR: 9 return "Guitar"; 10 case BANJO: 11 return "Banjo"; 12 case DOBRO: 13 return "Dobro"; 14 case FIDDLE: 15 return "Fiddle"; 16 case BASS: 17 return "Bass"; 18 case MANDOLIN: 19 return "Mandolin"; 20 default: 21 return "Unspecified"; 22 } 23 } 24 }
Style.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public enum Style { 4 A, F; 5 6 public String toString(){ 7 switch(this){ 8 case A: 9 return "a"; 10 case F: 11 return "F"; 12 default: 13 return "kong"; 14 } 15 } 16 }
Type.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public enum Type { 4 ACOUSTIC, ELECTRIC; 5 6 public String toString(){ 7 switch(this){ 8 case ACOUSTIC: 9 return "acoustic"; 10 case ELECTRIC: 11 return "electric"; 12 default: 13 return ""; 14 } 15 } 16 }
Wood.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public enum Wood { 4 INDIAN_ROSEWOOD, BRAZILIAN_ROSEWOOD, ALDER, MAPLE, SITKA, MAHOGANY, ADIRONDACK; 5 6 public String toString(){ 7 switch(this){ 8 case INDIAN_ROSEWOOD: 9 return "Indian Rosewood"; 10 case BRAZILIAN_ROSEWOOD: 11 return "Brazilian Rosewood"; 12 case ALDER: 13 return "Alder"; 14 case MAPLE: 15 return "Maple"; 16 case SITKA: 17 return "Sitka"; 18 case MAHOGANY: 19 return "Mahogany"; 20 case ADIRONDACK: 21 return "Adirondack"; 22 default: 23 return ""; 24 } 25 } 26 }
Instrument.java:
1 package com.headfirst.instrumentfinalversion; 2 3 public class Instrument { 4 private String serialNumber; 5 private double price; 6 private InstrumentSpec spec; 7 8 public Instrument(String serialNumber, double price, InstrumentSpec spec){ 9 this.serialNumber = serialNumber; 10 this.price = price; 11 this.spec = spec; 12 } 13 14 public String getSerialNumber(){ 15 return serialNumber; 16 } 17 18 public double getPrice(){ 19 return price; 20 } 21 22 public InstrumentSpec getSpec(){ 23 return spec; 24 } 25 }
InstrumentSpec.java:
1 package com.headfirst.instrumentfinalversion; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.Map; 6 7 public class InstrumentSpec { 8 private Map properties; 9 10 public InstrumentSpec(Map properties){ 11 if(properties == null){ 12 this.properties = new HashMap(); 13 }else{ 14 this.properties = new HashMap(properties); 15 } 16 } 17 18 public Object getProperty(String propertyName){ 19 return properties.get(propertyName); 20 } 21 22 public Map getProperties(){ 23 return properties; 24 } 25 26 public boolean matches(InstrumentSpec otherSpec){ 27 for(Iterator i = otherSpec.getProperties().keySet().iterator(); i.hasNext();){ 28 String propertyName = (String) i.next(); 29 if(!properties.get(propertyName).equals(otherSpec.getProperty(propertyName))) 30 return false; 31 } 32 33 return true; 34 } 35 }
Inventory.java:
1 package com.headfirst.instrumentfinalversion; 2 3 import java.util.Iterator; 4 import java.util.LinkedList; 5 import java.util.List; 6 7 public class Inventory { 8 private List inventory; 9 10 public Inventory(){ 11 inventory = new LinkedList(); 12 } 13 14 public void addInstrument(String serialNumber, double price, InstrumentSpec spec){ 15 Instrument instrument = new Instrument(serialNumber, price, spec); 16 inventory.add(instrument); 17 } 18 19 public Instrument get(String serialNumber){ 20 for(Iterator i = inventory.iterator(); i.hasNext();){ 21 Instrument instrument = (Instrument) i.next(); 22 if(instrument.getSerialNumber().equals(serialNumber)) 23 return instrument; 24 } 25 26 return null; 27 } 28 29 public List search(InstrumentSpec searchSpec){ 30 List matchingInstruments = new LinkedList(); 31 for(Iterator i = inventory.iterator(); i.hasNext();){ 32 Instrument instrument = (Instrument) i.next(); 33 if(instrument.getSpec().matches(searchSpec)) 34 matchingInstruments.add(instrument); 35 } 36 37 return matchingInstruments; 38 } 39 }
FindInstrument.java:
1 package com.headfirst.instrumentfinalversion; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.Map; 7 8 public class FindInstrument { 9 10 private static void initializeInventory(Inventory inventory){ 11 Map properties = new HashMap(); 12 properties.put("InstrumentType", InstrumentType.GUITAR); 13 properties.put("builder", Builder.COLLINGS); 14 properties.put("model", "CJ"); 15 properties.put("type", Type.ACOUSTIC); 16 properties.put("numStrings", 6); 17 properties.put("topWood", Wood.INDIAN_ROSEWOOD); 18 properties.put("backWood", Wood.SITKA); 19 inventory.addInstrument("11277", 3999.95, new InstrumentSpec(properties)); 20 21 properties.put("builder", Builder.MARTIN); 22 properties.put("model", "D-18"); 23 properties.put("topWood", Wood.MAHOGANY); 24 properties.put("backWood", Wood.ADIRONDACK); 25 inventory.addInstrument("122784", 5495.95, new InstrumentSpec(properties)); 26 27 properties.put("builder", Builder.FENDER); 28 properties.put("model", "Stratocastor"); 29 properties.put("type", Type.ELECTRIC); 30 properties.put("topWood", Wood.ALDER); 31 properties.put("backWood", Wood.ALDER); 32 inventory.addInstrument("V9512", 1549.95, new InstrumentSpec(properties)); 33 34 properties.put("builder", Builder.GIBSON); 35 properties.put("model", "Les Paul"); 36 properties.put("topWood", Wood.MAPLE); 37 properties.put("backWood", Wood.MAPLE); 38 inventory.addInstrument("70108276", 2295.95, new InstrumentSpec(properties)); 39 40 properties.put("model", "SG '61 Reissue"); 41 properties.put("topWood", Wood.MAHOGANY); 42 properties.put("backWood", Wood.MAHOGANY); 43 inventory.addInstrument("82765501", 1890.95, new InstrumentSpec(properties)); 44 45 properties.put("InstrumentType", InstrumentType.MANDOLIN); 46 properties.put("model", "F-5G"); 47 properties.put("type", Type.ACOUSTIC); 48 properties.remove("numStrings");//假如使用相同的properties Map,别忘了为Mandolin移除numStrings 49 properties.put("topWood", Wood.MAPLE); 50 properties.put("backWood", Wood.MAPLE); 51 inventory.addInstrument("9019920", 5495.95, new InstrumentSpec(properties)); 52 53 properties.put("InstrumentType", InstrumentType.BANJO); 54 properties.put("model", "RB-3 Wreath"); 55 properties.put("type", Type.ACOUSTIC); 56 properties.remove("topWood"); 57 properties.put("numStrings", 5); 58 inventory.addInstrument("8900231", 2945.95, new InstrumentSpec(properties)); 59 } 60 61 public static void main(String[] args){ 62 //Set up Rick's inventory 63 Inventory inventory = new Inventory(); 64 initializeInventory(inventory); 65 66 Map properties = new HashMap(); 67 properties.put("builder", Builder.GIBSON); 68 properties.put("backWood", Wood.MAPLE); 69 InstrumentSpec clientSpec = new InstrumentSpec(properties); 70 71 List matchingInstruments = inventory.search(clientSpec); 72 if(!matchingInstruments.isEmpty()){ 73 System.out.println("You might like these instruments:"); 74 for(Iterator i = matchingInstruments.iterator(); i.hasNext();){ 75 Instrument instrument = (Instrument)i.next(); 76 InstrumentSpec spec = instrument.getSpec(); 77 System.out.println("We have a " + spec.getProperty("instrumentType") + " with the following properties:"); 78 for(Iterator j = spec.getProperties().keySet().iterator(); j.hasNext();){ 79 String propertyName = (String)j.next(); 80 if(propertyName.equals("instrumentType")) 81 continue; 82 System.out.println(" " + propertyName + ": " + spec.getProperty(propertyName)); 83 } 84 System.out.println(" You can have this " + spec.getProperty("instrumentType") + " for $" + instrument.getPrice() + " ---"); 85 86 } 87 }else{ 88 System.out.println("Sorry, we have nothing for you ."); 89 } 90 } 91 92 93 }
上面的代码好好看一下,很值得品味,现在我的水平认为这是一段我从没有想过的,真是简单可行。
运行结果:
好的知识,分享给大家。
参考网址:
equalsIgnoreCase():http://blog.csdn.net/yujian_bing/article/details/8171379
Iterator keySet():https://zhidao.baidu.com/question/1303782909568685779.html
同一个Map键值对覆盖问题:http://blog.csdn.net/wide288/article/details/72828000
这一章很重要,学会思路,而不是学会敲代码!