23种设计模式上篇

创建型模式,共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;
    }
}

 

posted @ 2019-09-19 14:10  踏月而来  阅读(191)  评论(0编辑  收藏  举报