详解设计模式的三种创建模式。。。

 

目录

什么是设计模式?

设计模式的分类

创建模式

        单例模式

        单例模式--饿汉模式

        单例模式--懒汉模式

        单例模式--静态内部类

        单例模式--枚举

        工厂模式

        简单工厂模式--顾客需要给出清单

        工厂方法模式--根据工厂能产生什么顾客拿什么

        抽象工厂模式

        原型模式

        浅克隆-- 利用Object中clone()实现

        深度克隆

PS


什么是设计模式?

        对于设计人员,特别是开发人员吗,往往受限于眼界或经验不能够体会到设计原则的实用性,或者在处理具体问题时,不知道如何把设计原则应用到到设计和代码,因此产生了“设计模式”。

        随着参与的项目越来越多,人们发现:很多问题并不是一个项目中出现的,它会在很多的项目中出现。于是人们就把这些问题总结出来,然后给出了解决这些问题的方案,而这些方案同城为"设计模式"(解决问题的套路)。

设计模式的分类

        经过漫长岁月沉淀,人们总结出23种设计模式,通分为三大类:

  1.         创建模式:创建一些特殊的对象,或者在特殊要求下创建对象
  2.         结构模式:主要利用组合/聚合或者继承,让类与类能够形成某种关联关系--代理
  3.         行为模式:刻画了类和对象交换及分配职责的方式

 

创建模式

        作用:创建一些特殊的对象,或者特殊要求下创建对象

        单例模式

        是一种创建型的设计模式,涉及的是如何创建对象。单例模式的核心:无论使用该类方法多少次,都只产生一个该类对象,可以减少系统内存的消耗。

        单例模式--饿汉模式

public class Singleton {
    //当构造方法私有化后,无法在当前类的外部去通过构造方法产生对象 
    // 创建本类的私有构造方法
    private Singleton(){}
    private static Singleton singleton = new Singleton();
   	// 提供一个静态方法 返回当前的对象
    public static Singleton getInstance(){
        return singleton;
    }
}

        【注意】

        类加载时,会直接实例化单例对象,以后都返回该对象的引用。

        优点:没有加锁,执行效率高,线程安全的实例

        缺点:类加载时,会直接实例化单例对象,不管我有没有使用到该单例对象,浪费内存

        单例模式--懒汉模式

 public static LazySingleton getInstance(){
        if(singleton == null){// 判断对象是否被初始化
            // 对象没有被初始化,则加上类锁
            synchronized (LazySingleton.class){
                // 同时只有一个线程能够到这里
                if(singleton == null){
                    // 创建实例对象
                    singleton = new LazySingleton();
                }
            }
        }
        // 实例对象的引用
        return singleton;
    }

        【注意】

        双重检验 首先先判断实例是否为null,
        为null则使用synchronized锁住类 ,
        然后在同步块中,再一次判断实例是否为null,为null则初始化实例。

        优点:线程安全,且效率高的) 把锁的粒度变小,只锁第一次初始化时。

        单例模式--静态内部类

public class InnerSingleton {
    private InnerSingleton(){}
    // 静态内部类
    private static class Inner{
        private static InnerSingleton instance = new InnerSingleton();
    }
    public static InnerSingleton getInstance(){
        return Inner.instance;
    }

}

        【注意】

        通过静态内部类 完成单例模式的创建。

        在外部类加载时,并不会加载内部类,也就是不会执行new 实例(),这属于懒加载。

        只有第一次调用getInstance方法时,才会加载。

        单例模式--枚举

public class EnumSingleton {
    private EnumSingleton(){}
    private static enum SinEnum{
        // 自定义的枚举值
        TEST;
        private EnumSingleton es = new EnumSingleton();
    }
    public static EnumSingleton getInstance(){
        SinEnum s = SinEnum.TEST;
        return s.es;
    }
}

        【注意】

        通过枚举创建 单例模式。

        不常用

        工厂模式

        将使用者和对象的生产者进行分离。

        在工厂模式中,几乎都有三种角色,工厂(抽象工厂、具体工厂) 产品(抽象产品、具体产品) 使用者。使用者想要使用产品,不用自己去生产产品,把生产的动作交给工厂去做,使用者只需要从工厂提供产品的位置(方法)去拿就好。

        简单工厂模式--顾客需要给出清单

        例:不同类拥有同一行为。

        先定义一个产品接口,拥有共通的方法。

public interface Product {
    public void play();
}

        不同类型的产品实现该接口

public class Phone implements Product{
    @Override
    public void play() {
        System.out.println("play phone");
    }
}

        不同类型的产品实现该接口

public class IPad implements Product{
    @Override
    public void play() {
        System.out.println("play IPad");
    }
}

        创建一个工厂类

public class Factory {

    public Product getProduct(String type){
        if(type == null){
            return null;
        }
        if(type.equals("Phone")){
            System.out.println("生产 Phone");
            return new Phone();
        }else if(type.equals("IPad")){
            System.out.println("生产 IPad");
            return new IPad();
        }
        return null;
    }
}

        创建一个顾客测试类

public class Test {
    public static void main(String[] args) {
        Factory factory = new Factory();
        // 需要一个手机,只需告知给工厂即可,不用管任何的细节,屏蔽了具体的实现
        Product phone = factory.getProduct("Phone");
        Product iPad = factory.getProduct("IPad");
        phone.play();
        iPad.play();
    }
}

        最后输出结果:

        生产 Phone

        Play Phone

        生产IPad

        Play IPad 

        工厂方法模式--根据工厂能产生什么顾客拿什么

        工厂可以产生统一品牌的商品,会根据商品去抽象工厂,对每一个产品,提供一个工厂实现类。

         先定义一个产品接口,拥有共通的方法。

public interface Product {
    public void play();
}

        创建工厂接口

public interface Factory {
    /** 方法返回值 抽象产品 */
    public Product create();

}

        不同类型的产品实现该接口

public class Phone implements Product{
    @Override
    public void play() {
        System.out.println("play phone");
    }
}

        同时创建该产品的生产工厂

public class PhoneFactory implements Factory{
    @Override
    public Product create() {
        System.out.println("生产 Phone");
        return new Phone();
    }
}

        不同类型的产品实现该接口

public class IPad implements Product{
    @Override
    public void play() {
        System.out.println("IPad play");
    }
}

        同时创建该产品的生产工厂

public class IPadFactory implements Factory {
    @Override
    public Product create() {
        System.out.println("生产 IPad");
        return new IPad();
    }
}

        创建顾客测试类

public class Test {
    public static void main(String[] args) {
        Factory factory = new PhoneFactory();
        Factory factory1 = new IPadFactory();
        Product phone = factory.create();
        Product iPad = factory1.create();
        phone.play();
        iPad.play();

    }
}

        输出结果:

        生产 Phone

        Play Phone

        生产 IPad

        IPad Play

        抽象工厂模式

        根据工厂能产生什么顾客拿什么,但是工厂能产生的产品会有多种品牌。

        超级工厂,可以生产不同品牌的各种产品,抽象出超级工厂,也要抽象出产品,然后根据不同的品牌给出该品牌商品的工工厂实现类。

        例:

        提供一个创建一系列相关或相互依赖对象的接口, 而无需指定他们具体的类。-- 创建模式

        代入场景:我们作为工厂老板,

        工厂目前可以代工ApplePhone、AppleIPad,

        拓展业务代工HuawePhone、HuaweiIPad---提供多个类去完成业务

        如果我还需要继续扩展业务XiaomiPhone、XiaoMiIPad,需要提供的类就也多

        所以为了工厂更好的发展,需要对工厂升级

        1.对生产的产品进行细化,然后抽象

        抽象产品---手机、平板

        2.具体产品类

        ApplePhone 和 AppleIPad

        HuaweiPhone 和 HuaweiIPad

        3.根据不同的品牌给出工厂(需要先对工厂进行抽象)

        3.1抽象工厂两个gong--造手机和造平板

        3.2 给出具体的Huawei工厂 和 Apple工厂

        原型模式

        根据一个已经存在的对象,利用克隆的方式,来创建一个和他一样的对象。

        浅克隆-- 利用Object中clone()实现

        1.让被克隆的类实现Cloneable接口

        2.重写clone方法,方法访问修饰符public

        3.对象.clone()的方式的到一个一样的对象

public class Man implements Cloneable, Serializable {
    /** 姓名 */
    private String name;

    // 调用Object的clone方法 浅度克隆
    public Man clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        return (Man) obj;
    }
}

        深度克隆

        1.克隆对象所涉及的自定义类,需要实现序列化接口

        2.在需要克隆的类中,添加一个方法,完成序列化反序列化即可。

// 深度克隆的实现
public class Man implements Cloneable, Serializable {
    /** 姓名 */
    private String name;

    public Man depthClone() throws IOException, ClassNotFoundException {
        // 获取对象信息,把当前对象写入另一块内存
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream objOut = new ObjectOutputStream(bo);
        objOut.writeObject(this);

        // 读取内存 创建对象
        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream objIn = new ObjectInputStream(bi);
        Object obj = objIn.readObject();
        return (Man) obj;
    }
}

        【注意】

        浅度克隆,可以克隆一样的对象,但是对象中属性,如果是引用类型,该属性会指向相同的引用。
        深度克隆,使用对象序列化克隆一样的对象。 如果属性为引用类型,不会再重复引用,它会重写创建同类型的数据完成引用。

PS

        对于设计模式而言,在使用过程中有几点需要大家注意:

        1.模式用在什么地方

        2.模式的名称---对模式的描述

        3.模式的具体实现

        4.模式使用后的优缺点,特别是当一个模式有多个方案时,要去了解这些多种方案的优缺点,才能够在合适使用选用合适的方案。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值