• 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;
        }
    }
  • 相关阅读:
    thinkphp 学习1-模型
    apache 2.4目录权限
    标头 header()函数的用法
    PHP面试题一
    php学习
    如何执行超过一百兆(100MB)的sql脚本?
    jquery-numberformatter插件
    xpath 获取父级,和同级
    Vue el-table 行编辑验证、重置
    Vue 弹窗一个新增编辑页面
  • 原文地址:https://www.cnblogs.com/moris5013/p/11549210.html
Copyright © 2020-2023  润新知