zoukankan      html  css  js  c++  java
  • 第五章.良好的设计

    聚合(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

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

  • 相关阅读:
    Nim or not Nim? hdu3032 SG值打表找规律
    Maximum 贪心
    The Super Powers
    LCM Cardinality 暴力
    Longge's problem poj2480 欧拉函数,gcd
    GCD hdu2588
    Perfect Pth Powers poj1730
    6656 Watching the Kangaroo
    yield 小用
    wpf DropDownButton 源码
  • 原文地址:https://www.cnblogs.com/lanshanxiao/p/7197905.html
Copyright © 2011-2022 走看看