策略模式-观察者模式-装饰者模式-工厂模式-单例模式
算是最近学设计模式(HEAD FIRST设计模式)的一个总结吧,力求用最精简的代码说明其设计本质。
第一个模式:策略模式
代码:
1 interface refuel { 2 public void fuelUp(); 3 } 4 5 6 class car { 7 refuel fuelType; 8 9 public void setFuelType(refuel type) { 10 this.fuelType = type; 11 } 12 13 public void fuelUp() { 14 fuelType.fuelUp(); 15 } 16 17 } 18 19 20 class fuelUpWith_93 implements refuel { 21 22 @Override 23 public void fuelUp() { 24 System.out.println("Fueled up with No.93 gasoline"); 25 } 26 27 } 28 29 30 class fuelUpWith_97 implements refuel { 31 32 @Override 33 public void fuelUp() { 34 System.out.println("Fueled up with No.97 gasoline"); 35 } 36 37 }
说明:汽车都需要加油,但是不同汽车加不同的油,通过让汽车持有一个具体实现加油算法的对象(通常向上转型为其接口),在汽车加油的时候直接调用这个接口,让其自己实现这种汽车加油的相关算法。
设计思想:解耦合,这个设计模式最大的优点是:能保证复用所有相同的代码(只要你的汽车持有了其使用的汽油类型),又能保证当你需要一种新的实现的时候可以快速加入进去(写一种实现基础接口的算法实现)而不需要修改原有代码。
第二个设计模式:观察者模式
代码(JAVA内置实现):
1 import java.util.Observable; 2 import java.util.Observer; 3 4 public class Main { 5 6 public static void main(String[] args) { 7 School highSchool = new School(); 8 Student Jack = new Student("Jack"); 9 Student Tom = new Student("Tom"); 10 Jack.register(highSchool); 11 Tom.register(highSchool); 12 highSchool.termBegins(); 13 } 14 } 15 16 17 class School extends Observable { 18 19 public void termBegins() { 20 this.setChanged(); 21 this.notifyObservers(); 22 } 23 24 } 25 26 27 class Student implements Observer { 28 29 Observable o; 30 String name; 31 32 public Student(String name) { 33 this.name = new String(name); 34 } 35 36 public void register(Observable o) { 37 this.o = o; 38 o.addObserver(this); 39 } 40 41 @Override 42 public void update(Observable o, Object arg) { 43 if (o instanceof School) { 44 System.out.println(name + " go to schoole"); 45 } 46 } 47 48 }
代码(手动实现):
1 import java.util.ArrayList; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 Student Jack = new Student("Jack"); 7 Student Tom = new Student("Tom"); 8 School highSchool = new School(); 9 highSchool.register(Jack); 10 highSchool.register(Tom); 11 highSchool.termBegins(); 12 } 13 } 14 15 16 class School { 17 18 ArrayList<Student> stuList = new ArrayList<Student>(); 19 20 public void register(Student stu) { 21 stuList.add(stu); 22 } 23 24 public void termBegins() { 25 this.notifyObservers(); 26 System.out.println("Welcome to school!"); 27 } 28 29 private void notifyObservers() { 30 for (Student stu : stuList) { 31 stu.update(); 32 } 33 } 34 } 35 36 37 class Student { 38 39 String name; 40 41 public Student(String name) { 42 this.name = new String(name); 43 } 44 45 public void update() { 46 System.out.println(name + " go to school"); 47 } 48 49 }
说明:把学生(观察者)对象交给学校(被观察者)。当学校开学时,一个一个去“通知”,让其持有的学生对象作出对应的反应。
设计思想:当需要变化的时候通知观察者们。Swing组件中大量用到(反应鼠标点击消息等等)。其他没啥很特别的东西。
第三个设计模式:装饰者模式
代码:
1 public class Main { 2 3 public static void main(String[] args) { 4 coffee myCoffee = new Mocha(new Milk(new regularCoffee())); 5 System.out.println(myCoffee.getName()); 6 } 7 } 8 9 10 interface coffee { 11 12 public int getCost(); 13 14 public String getName(); 15 16 } 17 18 19 class regularCoffee implements coffee { 20 21 @Override 22 public int getCost() { 23 return 5; // 最最普通的一杯咖啡底价5元 24 } 25 26 @Override 27 public String getName() { 28 return "咖啡"; // 最最普通的咖啡 29 } 30 31 } 32 33 34 abstract class coffeeDecorator implements coffee { 35 36 coffee oriCoffee; 37 38 } 39 40 41 class Milk extends coffeeDecorator { // 牛奶,加牛奶的修饰器 42 43 public Milk(coffee c) { 44 this.oriCoffee = c; 45 } 46 47 @Override 48 public int getCost() { 49 return oriCoffee.getCost() + 3; // 加一份牛奶再加3元 50 } 51 52 @Override 53 public String getName() { 54 return "牛奶" + oriCoffee.getName(); // 加一份牛奶的话,名字上也要加一份牛奶前缀 55 } 56 57 } 58 59 60 class Mocha extends coffeeDecorator { // 摩卡,加巧克力的修饰器 61 62 public Mocha(coffee c) { 63 this.oriCoffee = c; 64 } 65 66 @Override 67 public int getCost() { 68 return oriCoffee.getCost() + 4; // 加一份巧克力再叫4元 69 } 70 71 @Override 72 public String getName() { 73 return "摩卡" + oriCoffee.getName(); // 加一份巧克力的话,名字也加一个前缀 74 } 75 76 }
说明:每一次新建一个装饰者(Mocha或者Milk或者你写的别的什么),都依赖于一个传入的参数(目前的咖啡),在这个基础上继续添加装饰。
设计思想:一些类可能有自由组合的可能(比如咖啡),你很难一次把他们写全(从设计上也不应该如此),于是便应该用装饰者模式让使用者自己去搭配。每一次经过修饰就在传入参数的基础上进行修改。
第四个设计模式:工厂模式
首先要说的是工厂模式这个名字让人迷惑,因为很多模式好像都和工厂模式有关系:
1,静态工厂模式 : 一般是说用静态方法写的简单工厂模式。
2,简单工厂模式 :就是一个类,里面封装了某个类的构造方法,不仅调配构造参数,也许还有别的工作要做。
3,工厂方法模式 :在工厂中定义一个创建对象的接口,但是让子类去实现(通过Abstract)具体的创建过程。(和模板方法模式有点像)
4,抽象工厂模式 :提供一个接口,用来创建相关或依赖对象的家族。
关于工厂方法模式和抽象工厂模式可以看:看这篇文章
第五个设计模式:单例模式
代码(饿汉模式):
1 class Singleton { 2 3 private static Singleton instance = new Singleton(); 4 5 private Singleton() { 6 7 } 8 9 public static Singleton getInstance() { 10 return instance; 11 } 12 13 }
说明:饿汉模式就是直接在类的静态字段中写上一个实例对象。由<clinit>方法自动在类加载结束的时候进行创建。JVM会保证类的加载线程安全,所以这种情况基本上不需要考虑多线程情况下的线程安全。但是问题还是有:生命周期不可以控制,这个类一加载就存在一个实例对象。
代码(懒汉模式,双重检查模式+volatile):
1 class Singleton { 2 3 private volatile static Singleton instance; 4 5 private Singleton() { 6 7 } 8 9 public static Singleton getInstance() { 10 if (instance == null) { 11 synchronized (Singleton.class) { 12 if (instance == null) { 13 return new Singleton(); 14 } 15 } 16 } 17 return instance; 18 } 19 }
说明:看这篇文章的说明
设计思想:很多类只需要有一个实例,也许只能有一个实例,当尝试获取多个实例时会返回相同一个实例对象(或者返回null或者报错)。