java编程思想中的设计模式

来源:互联网 发布:java wait 当前线程 编辑:程序博客网 时间:2024/06/07 07:14

1命令设计模式

命令设计模式首先需要一个只有单一方法的接口,然后从该接口实现具有各自不同的行为的多个子类。接下来,程序员就可以构造命令对象,并在需要的时候使用它们:

package com;import java.util.*;import static com.AlarmPoints.*;enum AlarmPoints {  STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,  OFFICE4, BATHROOM, UTILITY, KITCHEN}interface Command { void action(); }public class EnumMaps {  public static void main(String[] args) {    EnumMap<AlarmPoints,Command> em =      new EnumMap<AlarmPoints,Command>(AlarmPoints.class);    em.put(KITCHEN, new Command() {      public void action() { print("Kitchen fire!"); }    });    em.put(BATHROOM, new Command() {      public void action() { print("Bathroom alert!"); }    });    for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {      printnb(e.getKey() + ": ");      e.getValue().action();    }    try { // If there's no value for a particular key:      em.get(UTILITY).action();    } catch(Exception e) {      print(e);    }  }  public static void print(Object obj) {    System.out.println(obj);  }  public static void printnb(Object obj) {    System.out.print(obj);  }} /* Output:BATHROOM: Bathroom alert!KITCHEN: Kitchen fire!java.lang.NullPointerException*///:~

2职责链设计模式

程序员以多种不同的方式来解决一个问题,然后将它们链接起来。当一个请求到来时,它遍历这个链,直到链中的某个解决方案能够处理该请求。

下面的代码中,每一次尝试可以看作一个策略。

package com;//: enumerated/PostOffice.java// Modeling a post office.import java.util.*;class Enums {  private static Random rand = new Random(47);  public static <T extends Enum<T>> T random(Class<T> ec) {    return random(ec.getEnumConstants());  }  public static <T> T random(T[] values) {    return values[rand.nextInt(values.length)];  }}class Mail {  // The NO's lower the probability of random selection:  enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}  enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}  enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4}  enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}  enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5}  GeneralDelivery generalDelivery;  Scannability scannability;  Readability readability;  Address address;  ReturnAddress returnAddress;  static long counter = 0;  long id = counter++;  public String toString() { return "Mail " + id; }  public String details() {    return toString() +      ", General Delivery: " + generalDelivery +      ", Address Scanability: " + scannability +      ", Address Readability: " + readability +      ", Address Address: " + address +      ", Return address: " + returnAddress;  }  // Generate test Mail:  public static Mail randomMail() {    Mail m = new Mail();    m.generalDelivery= Enums.random(GeneralDelivery.class);    m.scannability = Enums.random(Scannability.class);    m.readability = Enums.random(Readability.class);    m.address = Enums.random(Address.class);    m.returnAddress = Enums.random(ReturnAddress.class);    return m;  }  public static Iterable<Mail> generator(final int count) {    return new Iterable<Mail>() {      int n = count;      public Iterator<Mail> iterator() {        return new Iterator<Mail>() {          public boolean hasNext() { return n-- > 0; }          public Mail next() { return randomMail(); }          public void remove() { // Not implemented            throw new UnsupportedOperationException();          }        };      }    };  }}public class PostOffice {  enum MailHandler {    GENERAL_DELIVERY {      boolean handle(Mail m) {        switch(m.generalDelivery) {          case YES:            print("Using general delivery for " + m);            return true;          default: return false;        }      }    },    MACHINE_SCAN {      boolean handle(Mail m) {        switch(m.scannability) {          case UNSCANNABLE: return false;          default:            switch(m.address) {              case INCORRECT: return false;              default:                print("Delivering "+ m + " automatically");                return true;            }        }      }    },    VISUAL_INSPECTION {      boolean handle(Mail m) {        switch(m.readability) {          case ILLEGIBLE: return false;          default:            switch(m.address) {              case INCORRECT: return false;              default:                print("Delivering " + m + " normally");                return true;            }        }      }    },    RETURN_TO_SENDER {      boolean handle(Mail m) {        switch(m.returnAddress) {          case MISSING: return false;          default:            print("Returning " + m + " to sender");            return true;        }      }    };    abstract boolean handle(Mail m);  }  static void handle(Mail m) {    for(MailHandler handler : MailHandler.values())      if(handler.handle(m))        return;    print(m + " is a dead letter");  }  public static void main(String[] args) {    for(Mail mail : Mail.generator(10)) {      print(mail.details());      handle(mail);      print("*****");    }  }  public static void print(Object obj) {    System.out.println(obj);  }} /* Output:Mail 0, General Delivery: NO2, Address Scanability: UNSCANNABLE, Address Readability: YES3, Address Address: OK1, Return address: OK1Delivering Mail 0 normally*****Mail 1, General Delivery: NO5, Address Scanability: YES3, Address Readability: ILLEGIBLE, Address Address: OK5, Return address: OK1Delivering Mail 1 automatically*****Mail 2, General Delivery: YES, Address Scanability: YES3, Address Readability: YES1, Address Address: OK1, Return address: OK5Using general delivery for Mail 2*****Mail 3, General Delivery: NO4, Address Scanability: YES3, Address Readability: YES1, Address Address: INCORRECT, Return address: OK4Returning Mail 3 to sender*****Mail 4, General Delivery: NO4, Address Scanability: UNSCANNABLE, Address Readability: YES1, Address Address: INCORRECT, Return address: OK2Returning Mail 4 to sender*****Mail 5, General Delivery: NO3, Address Scanability: YES1, Address Readability: ILLEGIBLE, Address Address: OK4, Return address: OK2Delivering Mail 5 automatically*****Mail 6, General Delivery: YES, Address Scanability: YES4, Address Readability: ILLEGIBLE, Address Address: OK4, Return address: OK4Using general delivery for Mail 6*****Mail 7, General Delivery: YES, Address Scanability: YES3, Address Readability: YES4, Address Address: OK2, Return address: MISSINGUsing general delivery for Mail 7*****Mail 8, General Delivery: NO3, Address Scanability: YES1, Address Readability: YES3, Address Address: INCORRECT, Return address: MISSINGMail 8 is a dead letter*****Mail 9, General Delivery: NO1, Address Scanability: UNSCANNABLE, Address Readability: YES2, Address Address: OK1, Return address: OK4Delivering Mail 9 normally******///:~


3模板方法

一些功能在基类中实现,并且其一个或多个抽象方法在派生类中定义,这种结构在设计模式中称为模板方法。

例如下面的PairManager类:

//: concurrency/CriticalSection.java// Synchronizing blocks instead of entire methods. Also// demonstrates protection of a non-thread-safe class// with a thread-safe one.package com;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import java.util.*;class Pair { // Not thread-safe  private int x, y;  public Pair(int x, int y) {    this.x = x;    this.y = y;  }  public Pair() { this(0, 0); }  public int getX() { return x; }  public int getY() { return y; }  public void incrementX() { x++; }  public void incrementY() { y++; }  public String toString() {    return "x: " + x + ", y: " + y;  }  public class PairValuesNotEqualException  extends RuntimeException {    public PairValuesNotEqualException() {      super("Pair values not equal: " + Pair.this);    }  }  // Arbitrary invariant -- both variables must be equal:  public void checkState() {    if(x != y)      throw new PairValuesNotEqualException();  }}// Protect a Pair inside a thread-safe class:abstract class PairManager {  AtomicInteger checkCounter = new AtomicInteger(0);  protected Pair p = new Pair();  private List<Pair> storage =    Collections.synchronizedList(new ArrayList<Pair>());  public synchronized Pair getPair() {    // Make a copy to keep the original safe:    return new Pair(p.getX(), p.getY());  }  // Assume this is a time consuming operation  protected void store(Pair p) {    storage.add(p);    try {      TimeUnit.MILLISECONDS.sleep(50);    } catch(InterruptedException ignore) {}  }  public abstract void increment();}// Synchronize the entire method:class PairManager1 extends PairManager {  public synchronized void increment() {    p.incrementX();    p.incrementY();    store(getPair());  }}// Use a critical section:class PairManager2 extends PairManager {  public void increment() {    Pair temp;    synchronized(this) {      p.incrementX();      p.incrementY();      temp = getPair();    }    store(temp);  }}class PairManipulator implements Runnable {  private PairManager pm;  public PairManipulator(PairManager pm) {    this.pm = pm;  }  public void run() {    while(true)      pm.increment();  }  public String toString() {    return "Pair: " + pm.getPair() +      " checkCounter = " + pm.checkCounter.get();  }}class PairChecker implements Runnable {  private PairManager pm;  public PairChecker(PairManager pm) {    this.pm = pm;  }  public void run() {    while(true) {      pm.checkCounter.incrementAndGet();      pm.getPair().checkState();    }  }}public class CriticalSection {  // Test the two different approaches:  static void  testApproaches(PairManager pman1, PairManager pman2) {    ExecutorService exec = Executors.newCachedThreadPool();    PairManipulator      pm1 = new PairManipulator(pman1),      pm2 = new PairManipulator(pman2);    PairChecker      pcheck1 = new PairChecker(pman1),      pcheck2 = new PairChecker(pman2);    exec.execute(pm1);    exec.execute(pm2);    exec.execute(pcheck1);    exec.execute(pcheck2);    try {      TimeUnit.MILLISECONDS.sleep(500);    } catch(InterruptedException e) {      System.out.println("Sleep interrupted");    }    System.out.println("pm1: " + pm1 + "\npm2: " + pm2);   System.exit(0);  }  public static void main(String[] args) {    PairManager      pman1 = new PairManager1(),      pman2 = new PairManager2();    testApproaches(pman1, pman2);  }} /* Output: (Sample)pm1: Pair: x: 15, y: 15 checkCounter = 272565pm2: Pair: x: 16, y: 16 checkCounter = 3956974*///:~

4策略设计模式

Delayed接口有一个方法为getDelay(TimeUnit unit),这个方法强制我们去使用TimeUnit类,可以很容易地转换单位而无需作任何声明,这是策略设计模式的一个简单示例,在这种模式中,算法的一部分是作为参数传递进来的。