创建型模式,共5种:
(1)工厂方法模式
(2)抽象工厂模式
(3)单例模式
(4)建造者模式
(5)原型模式
简单工厂模式
在GOF23种设计模式中,简单工厂模式并不包含在其中。他是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特例
public abstract class Coffee { /** * 获取coffee名称 * @return */ public abstract String getName(); } public class Americano extends Coffee { @Override public String getName() { return "美式咖啡"; } } public class Cappuccino extends Coffee { @Override public String getName() { return "卡布奇诺"; } } public class Latte extends Coffee { @Override public String getName() { return "拿铁"; } } public class SimpleFactory { /** * 通过类型获取Coffee实例对象 * @param type 咖啡类型 * @return */ public static Coffee createInstance(String type){ if("americano".equals(type)){ return new Americano(); }else if("cappuccino".equals(type)){ return new Cappuccino(); }else if("latte".equals(type)){ return new Latte(); }else{ throw new RuntimeException("type["+type+"]类型不可识别,没有匹配到可实例化的对象!"); } } public static void main(String[] args) { Coffee latte = SimpleFactory.createInstance("latte"); System.out.println("创建的咖啡实例为:" + latte.getName()); Coffee cappuccino = SimpleFactory.createInstance("cappuccino"); System.out.println("创建的咖啡实例为:" + cappuccino.getName()); } }
定义了一个创建对象的工厂接口,把类实例化推迟到了工厂的子类,与简单工厂模式相比,假如要新增一个产品,他只需要新增一个Fruit的实现,一个FruitFactory的实现即可。其他的不用修改。而简单工厂要修改工厂类中的代码
public interface Fruit { public void get(); } public class Apple implements Fruit { public void get() { System.out.println("吃苹果"); } } public interface FruitFactory { public Fruit getFruit(); } public class AppleFactory implements FruitFactory { public Fruit getFruit() { return new Apple(); } } public class Banana implements Fruit { public void get() { System.out.println("吃香蕉"); } } public class BananaFactory implements FruitFactory { public Fruit getFruit() { return new Banana(); } } public class MainClass { public static void main(String[] args) { FruitFactory ff = new AppleFactory(); Fruit apple = ff.getFruit(); apple.get(); FruitFactory ff2 = new BananaFactory(); Fruit banana = ff2.getFruit(); banana.get(); } }
抽象工厂模式
用于创建一系列相关或相依赖的产品系列 。与工厂方法相比,他是生产一系列相互依赖的产品
// 抽象食物 interface Food { public String getFoodName(); } // 抽象餐具 interface TableWare { public String getToolName(); } // 抽象工厂 interface KitchenFactory { public Food getFood(); public TableWare getTableWare(); } //具体食物 Apple 的定义如下 class Apple implements Food { public String getFoodName() { return "apple"; } } //具体餐具 Knife 的定义如下 class Knife implements TableWare { public String getToolName() { return "knife"; } } // 以具体工厂 AKitchen 为例 class AKitchen implements KitchenFactory { public Food getFood() { return new Apple(); } public TableWare getTableWare() { return new Knife(); } } // 吃货要开吃了 public class Foodaholic { public void eat(KitchenFactory k) { System.out.println("A foodaholic is eating " + k.getFood().getFoodName() + " with " + k.getTableWare().getToolName()); } public static void main(String[] args) { Foodaholic fh = new Foodaholic(); KitchenFactory kf = new AKitchen(); fh.eat(kf); } }
单例模式
单例类只能保证有一个实例存在
/** * 懒汉式 * 这里的缺点是可能发生空指针异常,两个线程同时到达1处,第一个线程new一个实例返回了,第二个线程拿到的实例中的某些属性还是null,导致空指针异常,
* 这是由于第一个线程还没有完全实例化 instance */ public class Singleton1 { private static Singleton1 instance; private Singleton1() { } public static synchronized Singleton1 getInstance() { if (instance == null) { //1 instance = new Singleton1(); } return instance; } } /** * 饿汉式 * */ public class Singleton2 { private static Singleton2 instance = new Singleton2(); private Singleton2() { } public static Singleton2 getInstance() { return instance; } } /** * * 双重检查 * */ public class Singleton3 {
//volatile保证了可见性,和有序性,防止了饿汉式可能发生的空指针异常 private volatile static Singleton3 singleton; private Singleton3() { } public static Singleton3 getSingleton() { if (singleton == null) { synchronized (Singleton3.class) { if (singleton == null) { singleton = new Singleton3(); } } } return singleton; } }
建造者模式
生成一个复杂的产品时,将产品部件和组装过程分开,同样的组装过程可以生产出不同的产品
//产品 public class Meal { private String food; private String drink; public String getFood() { return food; } public void setFood(String food) { this.food = food; } public String getDrink() { return drink; } public void setDrink(String drink) { this.drink = drink; } } //Builder(抽象建造者) public abstract class MealBuilder { Meal meal = new Meal(); public abstract void buildFood(); public abstract void buildDrink(); public Meal getMeal() { return meal; } } //ConcreteBuilder(具体建造者),A套餐 public class MealA extends MealBuilder { public void buildDrink() { meal.setDrink("可乐"); } public void buildFood() { meal.setFood("薯条"); } } //ConcreteBuilder(具体建造者),B套餐 public class MealB extends MealBuilder { public void buildDrink() { meal.setDrink("柠檬果汁"); } public void buildFood() { meal.setFood("鸡翅"); } } //Director(指挥者) public class KFCWaiter { private MealBuilder mealBuilder; public KFCWaiter(MealBuilder mealBuilder) { this.mealBuilder = mealBuilder; } public Meal construct() { // 准备食物 mealBuilder.buildFood(); // 准备饮料 mealBuilder.buildDrink(); // 准备完毕,返回一个完整的套餐给客户 return mealBuilder.getMeal(); } } public class MainClass { public static void main(String[] args) { // 套餐A MealA a = new MealA(); // 准备套餐A的服务员 KFCWaiter waiter = new KFCWaiter(a); // 获得套餐 Meal mealA = waiter.construct(); System.out.print("套餐A的组成部分:"); System.out.println("食物:" + mealA.getFood() + "; " + "饮品:" + mealA.getDrink()); } }
原型模式(JDK里的clone就是原型模式的实现,Object的clone方法是native类型)
原型模式指的是复制原型对象来创建实例。使用原型模式创建的实例,具有与原型一样的数据
public class Student implements Cloneable, Serializable { /** * */ private static final long serialVersionUID = 1L; private int age; private String name; public Student() { } public Student(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [age=" + age + ", name=" + name + "]"; } @Override public Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } /** * @param args * @throws CloneNotSupportedException */ public static void main(String[] args) throws CloneNotSupportedException { Student student1 = new Student(20, "张三"); Student student2 = (Student) student1.clone(); student2.setAge(22);// 注意修改student2的age值 但是没有影响 student1的值 System.out.println("student1:" + student1.getName() + "-->" + student1.getAge()); System.out.println("student2:" + student2.getName() + "-->" + student2.getAge()); } } public class Teacher implements Cloneable, Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private Student student; public String getName() { return name; } public void setName(String name) { this.name = name; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } @Override public String toString() { return "Teacher [name=" + name + ", student=" + student + "]"; } @Override public Object clone() throws CloneNotSupportedException { // 浅拷贝 return super.clone(); // 深拷贝 // Teacher teacher = (Teacher)super.clone(); // teacher.setStudent((Student)this.getStudent().clone()); // return teacher; } public static void main(String[] args) throws CloneNotSupportedException { Student s1 = new Student(); s1.setAge(20); s1.setName("张三"); Teacher teacher1 = new Teacher(); teacher1.setName("小赵老师"); teacher1.setStudent(s1); // 为什么会出现以下结果, Teacher中的clone方法 Teacher teacher2 = (Teacher) teacher1.clone(); Student s2 = teacher2.getStudent(); s2.setName("李四"); s2.setAge(30); System.out.println("teacher1:" + teacher1); System.out.println("teacher2:" + teacher2); // 采用序列化完成深拷贝 // Teacher teacher2 = CloneUtils.clone(teacher1); // teacher2.setName("小赵老师1"); // Student s2 = teacher2.getStudent(); // s2.setName("李四"); // s2.setAge(30); // System.out.println("teacher1:"+teacher1); // System.out.println("teacher2:"+teacher2); } } public class CloneUtils { @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj){ T cloneObj = null; try { //写入字节流 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(obj); obs.close(); //分配内存,写入原始对象,生成新对象 ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); //返回生成的新对象 cloneObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } return cloneObj; } }