• 设计模式之创建型模式


    创建型模式主要是用于创建对象,主要分为5大类:工厂方法模式(factory method pattern)、抽象工厂模式(Abstract factory pattern)、单例模式(Singleton pattern)、建造者模式(Builder pattern)、原型模式(prototype pattern)。

    一、工厂方法模式(factory method pattern)

      工厂方法模式主要分为三种:普通工厂模式、多工厂方法模式、静态工厂方法模式

      1、普通工厂模式:创建一个工厂类,为有共同接口的类创建对象;通过传入的值和工厂类的判断条件进行匹配,创建不同的对象。

        

    //对象的共同接口
    public interface Phone {
        
        void call();
    }
    
    public class MiPhone implements Phone{
    
        @Override
        public void call() {
            System.out.println("雷布斯为你打call,,,,");
            
        }
    
    }
    
    public class IPhone implements Phone {
    
        @Override
        public void call() {
            System.out.println("果粉为你打call。。。。。。。。");
    
        }
    
    }
    
    public class HuaWeiPhone implements Phone {
    
        @Override
        public void call() {
            System.out.println("华为海军为你打call!!!!");
        }
    
    }
    
    
    //对象的生产工厂
    public class PhoneFactory {
        
        public Phone produce(String type){
            if("小米".equals(type)){
                return new MiPhone();
            }else if("华为".equals(type)){
                return new HuaWeiPhone();
            }else if("苹果".equals(type)){
                return new IPhone();
            }else {
                return null;
            }
        }
    
    }
    
    //测试类
    public class FactoryMethodPatternTest {
    
        public static void main(String[] args) {
            
            PhoneFactory phoneFactory = new PhoneFactory();
            Phone xiaomi = phoneFactory.produce("小米");
            Phone huawei = phoneFactory.produce("华为");
            Phone pingguo = phoneFactory.produce("苹果");
            
            xiaomi.call();
            huawei.call();
            pingguo.call();
        }
    
    }

      2、多工厂方法模式:对普通工厂方法模式进行改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,直接调用不同的方法来创建不同的对象,这样不容易出错。

      

    /**
    *只需要将工厂方法和调用方法修改一下
    */
    
    //多方法对象的生产工厂
    public class PhoneFactory {
        
        public Phone produceMiPhone(){
                return new MiPhone();
        }
        
        public Phone produceHuaweiPhone(){
            return new HuaWeiPhone();
        }
        
        public Phone produceIPhone(){
            return new IPhone();
        }
        
    }
    
    
    //测试类
    public class FactoryMethodPatternTest {
    
        public static void main(String[] args) {
            
            PhoneFactory phoneFactory = new PhoneFactory();
            Phone xiaomi = phoneFactory.produceMiPhone();
            Phone huawei = phoneFactory.produceHuaweiPhone();
            Phone pingguo = phoneFactory.produceIPhone();
            
            xiaomi.call();
            huawei.call();
            pingguo.call();
        }
    
    }

      

      3、静态工厂方法模式:将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    //静态方法对象的生产工厂
    public class PhoneFactory {
        
        public static Phone produceMiPhone(){
                return new MiPhone();
        }
        
        public static Phone produceHuaweiPhone(){
            return new HuaWeiPhone();
        }
        
        public static Phone produceIPhone(){
            return new IPhone();
        }
        
    }
    
    
    //测试类
    public class FactoryMethodPatternTest {
    
        public static void main(String[] args) {
            
            Phone xiaomi = PhoneFactory.produceMiPhone();
            Phone huawei = PhoneFactory.produceHuaweiPhone();
            Phone pingguo = PhoneFactory.produceIPhone();
            
            xiaomi.call();
            huawei.call();
            pingguo.call();
        }
    
    }

    二、抽象工厂模式(Abstract factory pattern)

      上面的工厂方法模式如果要扩展就必须修改代码,这样就违反了开闭原则。抽象工厂模式将对象的生产工厂也进行抽象,方便程序扩展。

    //对象生产工厂接口
    public interface PhoneFactory {
    
        Phone produce();
    }
    
    public class MiPhoneFactory implements PhoneFactory{
        
        @Override
        public Phone produce() {
            return new  MiPhone();
        }
        
    }
    
    public class HuaWeiPhoneFactory implements PhoneFactory{
        
        @Override
        public Phone produce() {
            return new HuaWeiPhone();
        }
    
    }
    
    
    public class IPhoneFactory implements PhoneFactory {
    
        @Override
        public Phone produce() {
            return new IPhone();
        }
    
    }
    
    
    //测试类
    public class AbstractFactoryPatternTest {
    
        public static void main(String[] args) {
            
            PhoneFactory miPhoneFactory = new MiPhoneFactory();
            PhoneFactory huaWeiFactory = new HuaWeiPhoneFactory();
            PhoneFactory iphoneFactory = new IPhoneFactory();
            
            Phone miPhone = miPhoneFactory.produce();
            Phone huaWeiPhone = huaWeiFactory.produce();
            Phone iPhone = iphoneFactory.produce();
            
            miPhone.call();
            huaWeiPhone.call();
            iPhone.call();
            
        }
    
    }

    三、单例模式(Singleton pattern):

      单例模式主要分为:饿汉式、懒汉式、双重检测锁、静态内部类、枚举类

      1、饿汉式:顾名思义就是很饥饿,还不需要该对象的时候就直接创建该对象。

      

    //饿汉单例模式
    public class Singleton {
        
        //在类的初始化阶段就直接创建好对象
        private static Singleton instance = new Singleton();
        
        //私有化构造方法,保证无法创建更多对象,该对象只能通过getInstance方法来进行获取
        private Singleton(){}
        
        public static Singleton getInstance(){
            return instance;
        }
    }

      2、懒汉式:需要用到该对象的时候才会区创建对象

    //懒汉单例模式,只在第一次需要的时候才会创建对象,有线程安全问题
    public class Singleton2 {
        
        private static Singleton2 instance = null;
        
        private Singleton2 (){}
        
        public static Singleton2 getInstance(){
            if( instance == null ){
                instance = new Singleton2();
            }
            
            return instance;
        }
    
    }
    //懒汉单例模式,只在第一次需要的时候才会创建对象,没有线程安全问题,但是每次取对象的时候都需要获取锁,影响效率
    public class Singleton3 {
        
        private static Singleton3 instance = null;
        
        private Singleton3 (){}
        
        public static synchronized Singleton3 getInstance(){
            if( instance == null ){
                instance = new Singleton3();
            }
            
            return instance;
        }
    
    }

      3、双重检测锁模式:在懒汉式基础上改进,效率比懒汉式要高。

    //双重检测锁单例模式,是线程安全的,并且只有前几次需要获取锁,效率比饿汉线程安全模式高。
    //但是由于jvm底层的原因,在创建对象的时候有可能出现指令重排,后面的线程获取了还未初始化的对象,并且去执行对应的方法,这样就会出现问题。
    //可以通过volatile 来防止指令重排
    public class Singleton4 {
        
        private static Singleton4 instance = null;
        
        private Singleton4 (){}
        
        public static Singleton4 getInstance(){
            if( instance == null ){
                synchronized (Singleton4.class) {
                    if( instance == null ){
                        instance = new Singleton4();
                    }
                }
            }
            
            return instance;
        }
    
    }

      3.1、补充

    //这种方式貌似能够解决双重检测锁的问题
    public class Singleton7 {
        
        private static Singleton7 instance = null;
        
        private Singleton7 (){}
        
        private static synchronized void createSingleton7(){
            instance  = new Singleton7();
        }
        
        public static Singleton7 getInstance(){
            if( instance == null ){
                synchronized (Singleton7.class) {
                    if( instance == null ){
                        createSingleton7();
                    }
                }
            }
            
            return instance;
        }
    
    }

      4、静态内部类模式:运用静态内部类的特性来构造单例

    //静态内部类单例模式,这种方式线程安全并且是懒加载
    public class Singleton5 {
        
        private Singleton5 (){}
        
        public static class SingletonContainer{
            private static Singleton5 instance = new Singleton5();
        }
        
        public static Singleton5 getInstance(){
            return SingletonContainer.instance;
        }
    
    }

      

      5、枚举类:枚举类的元素本身就是单例对象。

    //枚举类的元素就是单例的,并且无线程安全问题。在序列化和反序列化之后也能保证单例
    public enum Singleton6 {
        
        INSTANCE;
        
        //需要执行的操作
        public void doSomeThing(){}
    
    }

    四、建造者模式(Builder pattern)

      建造者模式又名创建者模式,是将一个复杂对象的构建过程与它的表示分离,从而使得相同的构建过程可以创建不同的表示;创建者模式隐藏了复杂对象的创建过程,它把复杂对象的构建加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

    与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

      主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

    public class Car {
        
        private String Body;
        
        private String wheel;
    
        public String getBody() {
            return Body;
        }
    
        public void setBody(String body) {
            Body = body;
        }
    
        public String getWheel() {
            return wheel;
        }
    
        public void setWheel(String wheel) {
            this.wheel = wheel;
        }
    
        @Override
        public String toString() {
            return "Car [Body=" + Body + ", wheel=" + wheel + "]";
        }
        
    }
    public interface Builder {
        
        void buildBody();
        
        void buildWheel();
    
        Car getCar();
    }
    
    
    public class BenzBuilder implements Builder {
        
        private String body;
        private String wheel;
        
        @Override
        public void buildBody() {
            this.body = "奔驰车身";
        }
    
        @Override
        public void buildWheel() {
            this.wheel = "奔驰轮子";
        }
    
        @Override
        public Car getCar() {
            Car car = new Car();
            car.setBody(body);
            car.setWheel(wheel);
            return car;
        }
    
    }
    //对车辆进行组装
    public class Director {
    
        private Builder builder;
        
        public Director(Builder builder){
            this.builder = builder;
        }
        
        public void setBuilder(Builder builder){
            this.builder = builder;
        }
        
        //组装车辆
        public Car constructCar(){
            builder.buildBody();
            builder.buildWheel();
            builder.buildWheel();
            builder.buildWheel();
            builder.buildWheel();
            
            return builder.getCar();
        } 
        
    }
    
    
    //测试
    public class BuilderTest {
    
        public static void main(String[] args) {
            
            Builder benzBuilder = new BenzBuilder();
            Director director2= new Director(benzBuilder);
            Car car2 = director2.constructCar();
            System.out.println(car2);
        }
    
    }

    五、原型模式(prototype pattern)

      原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。直接创建对象的代价比较大时,则采用这种模式。

      浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

      深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了。

      java中通过clone来实现对象的浅复制,一个原型类,只需要实现Cloneable接口,覆写clone方法就可以实现浅复制。通过实现Serializable 接口然后通过序列化和反序列化进行深度复制。

    public class Prototype implements Cloneable, Serializable {
    
        private static final long serialVersionUID = 1L;
        
        private String name;
        
        private List<String> list;
        
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<String> getList() {
            return list;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
        
        protected Object deepClone() throws IOException, ClassNotFoundException {
            /* 写入当前对象的二进制流 */  
            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
            ObjectOutputStream oos = new ObjectOutputStream(bos);  
            oos.writeObject(this);  
      
            /* 读出二进制流产生的新对象 */  
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
            ObjectInputStream ois = new ObjectInputStream(bis);  
            return ois.readObject();  
        }
    
        @Override
        public String toString() {
            return "Prototype [name=" + name + ", list=" + list + "]";
        }
    
    }
    public class PrototypeTest {
    
        public static void main(String[] args) throws Exception {
            Prototype p = new Prototype();
            p.setName("a");
            List<String> list = new ArrayList<>();
            list.add("b");
            p.setList(list);
            System.out.println(p);
            
            //浅复制
            Prototype p1 = (Prototype)p.clone();
            System.out.println(p1);
            
            //深复制
            Prototype p2 = (Prototype)p.deepClone();
            System.out.println(p2);
            
            System.out.println("------------------------------");    
            
            //修改原型的值,发现复制后的对象的值也被修改了
            list.add("c");
            p.setName("A");
            p.setList(list);
            System.out.println(p);
            System.out.println(p1);
            System.out.println(p2);
            
        }
    
    }

      

  • 相关阅读:
    ES6之6种遍历对象属性的方法
    css自定义滚动条样式,自定义文字选择样式,设置文字不被选择
    js img转换base64
    移动端rem造成的很多问题
    移动端边框1像素的问题
    【小练习1】如何制作“表单”
    2015-09-24 第六节课 (CSS补充和html 标签讲解、浏览器兼容性)
    2015-09-22 第四节课 CSS块级元素 行内元素 浮动 盒子模型 绝对定位、相当定位和固定定位
    2015-09-21 第三节课 css属性 border(边框)、background(背景)
    html你可能还不知道的一些知识点
  • 原文地址:https://www.cnblogs.com/kyleinjava/p/9724779.html
Copyright © 2020-2023  润新知