• 第五章.良好的设计


    聚合(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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    上面代码,如果有什么疑问,可以指出。

    根据吉他店长,不,应该叫乐器店长,的指示。我们来扩展和修改我们上面的代码,看有什么问题?

    我们只有一个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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    没有写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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

     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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    上面的代码好好看一下,很值得品味,现在我的水平认为这是一段我从没有想过的,真是简单可行。

    运行结果:

    好的知识,分享给大家。

    参考网址:

    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

    这一章很重要,学会思路,而不是学会敲代码!

  • 相关阅读:
    android的左右滑动效果实现-ViewFlipper
    ios学习之UISwipeGestureRecognizer手势识别
    iOS使用AVFoundation实现二维码扫描
    IOS开发之Core Location
    iOS中如何创建一个滑出式导航面板(1)
    消息推送之百度云推送Android集成与使用方法
    IOS开发之Storyboard应用
    用CocoaPods做iOS程序的依赖管理
    RelativeLayout 布局参数
    Android中获取应用程序(包)的信息-----PackageManager的使用
  • 原文地址:https://www.cnblogs.com/lanshanxiao/p/7197905.html
Copyright © 2020-2023  润新知