设计模式(学习笔记)(第二章,创建型模式)
创建型模式关注点怎样创建出对象将对象的创建和使用分离降低系统的耦合性使用者无需关注对象的创建细节对象的创建由相关的工厂来完成各种工厂模式对象的创建由一个建造者来完成建造者模式对象的创建由原来对象克隆完成原型模式对象始终在系统中只有一个实例单例模式1. 单例一个单一的类负责创建自己的对象同时确保系统中只有单个对象被创建。单例特点某个类只有一个实例构造器私有它必须自行创建这个实例自己编写实例化逻辑它必须自行向整个系统提供这个实例对外提供实例化方法packagesjms.Creational.Singleton;/** * 单例对象 */publicclassSingleObject{/** * 自行创建这个对象 * 根据这个对象创建的时机分为饿汉和懒汉 * 饿汉一开始就创建例如静态变量创建 * 懒汉我用到这个对象才创建在getInstance方法中创建 */privatevolatilestaticSingleObjectinstance;/** * 构造器私有 */privateSingleObject(){}/** * 向整个系统提供这个实例 * return *///懒汉第二种ifsynchronized方法锁创建锁太重,性能有影响// public synchronized static SingleObject getInstance(){publicstaticSingleObjectgetInstance(){//懒汉第一种if创建会有多线程问题。/*if(instancenull){ instance new SingleObject(); }*///懒汉第三种 双重检查锁volatile关键字防止指令重排if(instancenull){synchronized(SingleObject.class){if(instancenull){instancenewSingleObject();}}}returninstance;}publicstaticvoidmain(String[]args){SingleObjectinstanceSingleObject.getInstance();SingleObjectinstance2SingleObject.getInstance();System.out.println(instance);System.out.println(instance2);}}2. 原型原型模式Prototype Pattern是用于创建重复的对象同时又能保证性能。本体给外部提供一个克隆体进行使用。深拷贝浅拷贝packagesjms.Creational.Prototype;importlombok.Data;DatapublicclassUserimplementsCloneable{privateStringname;privateIntegerage;/** * 克隆对象的方法。 * return * throws CloneNotSupportedException */OverrideprotectedObjectclone()throwsCloneNotSupportedException{UserusernewUser();user.setName(name);user.setAge(age);returnuser;}}packagesjms.Creational.Prototype;importjava.util.HashMap;importjava.util.Map;publicclassGuiguMybatis{//缓存user.序列化和反序列化-深克隆privateMapString,UseruserCachenewHashMap();/** * 从数据库查数据 * return */publicUsergetUser(Stringusername)throwsException{Userusernull;//缓存中没有if(!userCache.containsKey(username)){//查询数据库usergetUserFromDb(username);}else{//从缓存中直接拿脏缓存问题//原型已经拿到但是不能直接给。本人useruserCache.get(username);System.out.println(从缓存中拿到的是user);//从这个对象快速得到一个克隆体克隆人原型模式user(User)user.clone();}returnuser;}privateUsergetUserFromDb(Stringname)throwsException{System.out.println(从数据库查到name);UserusernewUser();user.setName(name);user.setAge(18);//给缓存中放一个cloneuserCache.put(name,(User)user.clone());returnuser;}publicstaticvoidmain(String[]args)throwsException{GuiguMybatismybatisnewGuiguMybatis();//十分危险//得到的是克隆体Userzhangsan1mybatis.getUser(zhangsan);System.out.println(1zhangsan1);zhangsan1.setName(李四2.。。);System.out.println(zhangsan1自己改了zhangsan1);//得到的是克隆体Userzhangsan2mybatis.getUser(zhangsan);System.out.println(2--zhangsan2);//得到的是克隆体Userzhangsan3mybatis.getUser(zhangsan);System.out.println(3--zhangsan3);//得到的是克隆体Userzhangsan4mybatis.getUser(zhangsan);System.out.println(4--zhangsan4);System.out.println(zhangsan1zhangsan3);}}3.工厂模式工厂模式Factory Pattern提供了一种创建对象的最佳方式。我们不必关心对象的创建细节只需要根据不同情况获取不同产品即可。难点写好我们的工厂。3.1 简单 工厂三个角色Factory工厂角色 WuLinFactoryProduct抽象产品角色CarConcreteProduct具体产品角色 VanCar、MiniCar//抽象产品角色publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine开始运行了);}}//具体产品角色publicclassMiniCarextendsCar{publicMiniCar(){this.enginemini发动机;}}//具体产品角色publicclassVanCarextendsCar{publicVanCar(){this.enginev8发动机;}}//工厂角色publicclassWuLinFactory{publicCarnewCar(Stringtype){if(van.equals(type)){returnnewVanCar();}elseif(mini.equals(type)){returnnewMiniCar();}returnnull;}publicstaticvoidmain(String[]args){WuLinFactorywuLinFactorynewWuLinFactory();CarvanwuLinFactory.newCar(van);van.run();CarminiwuLinFactory.newCar(mini);mini.run();}}缺点违背开闭扩展不易3.2 工厂方法 多态工厂怎么把一个功能提升一个层次定义抽象抽象类接口抽象类接口 就会有多实现多实现自然就有多功能四个角色Product抽象产品ConcreteProduct具体产品Factory抽象工厂ConcreteFactory具体工厂//抽象产品publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine开始运行了);}}//具体产品publicclassMiniCarextendsCar{publicMiniCar(){this.enginemini发动机;}}//具体产品publicclassVanCarextendsCar{publicVanCar(){this.enginev8发动机;}}//抽象工厂publicabstractclassWuLinFactory{publicabstractCarnewCar();}//具体工厂publicclassWuLinMiniFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnewMiniCar();}}//具体工厂publicclassWuLinVanFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnewVanCar();}}//测试publicclassMainTest{publicstaticvoidmain(String[]args){WuLinFactoryfactorynewWuLinMiniFactory();Carcarfactory.newCar();car.run();WuLinFactoryfactory2newWuLinVanFactory();Carcar2factory2.newCar();car2.run();}}缺点系统复杂度增加产品单一4.抽象工厂产品等级结构产品等级结构即产品的 继承结构如一个抽象类是手机 其子类有小米手机、华为手机产品族在抽象工厂模式中产品族是指由同一个工厂生产的位于不同产品等级结构中的一组产品。当抽象工厂模式中每一个具体工厂类只创建一个产品对象也就是只存在一个产品等级结构时抽象工厂模式退化成工厂方法模式当工厂方法模式中抽象工厂与具体工厂合并提供一个统一的工厂来创建产品对象并将创建对象的工厂方法设计为静态方法时工厂方法模式退化成简单工厂模式。//抽象产品publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine开始运行了);}}//具体产品publicclassMiniCarextendsCar{publicMiniCar(){this.enginemini发动机;}}//具体产品publicclassVanCarextendsCar{publicVanCar(){this.enginev8发动机;}}publicabstractclassMask{publicIntegerprice;publicStringname;publicvoidprotectMe(){System.out.println(name的口罩,价格是:price);}}publicclassCommonMaskextendsMask{publicCommonMask(){this.price1;this.name普通口罩;}}publicclassN95MaskextendsMask{publicN95Mask(){this.price20;this.nameN95口罩;}}//抽象工厂publicabstractclassWuLinFactory{publicabstractCarnewCar();publicabstractMasknewMask();}//具体工厂publicclassWuLinMiniFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnewMiniCar();}OverridepublicMasknewMask(){returnnull;}}//具体工厂publicclassWuLinVanFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnewVanCar();}OverridepublicMasknewMask(){returnnull;}}publicclassWuLinCommonMaskFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnull;}OverridepublicMasknewMask(){returnnewCommonMask();}}publicclassWuLinN95MaskFactoryextendsWuLinFactory{OverridepublicCarnewCar(){returnnull;}OverridepublicMasknewMask(){returnnewN95Mask();}}publicclassMainTest{publicstaticvoidmain(String[]args){WuLinFactoryfactory1newWuLinVanFactory();Carcar1factory1.newCar();car1.run();WuLinFactoryfactory2newWuLinMiniFactory();Carcar2factory2.newCar();car2.run();WuLinFactoryfactory3newWuLinN95MaskFactory();Maskmask1factory3.newMask();mask1.protectMe();WuLinFactoryfactory4newWuLinCommonMaskFactory();Maskmask2factory4.newMask();mask2.protectMe();}}5.建造者产品角色ProductPhone抽象建造者BuilderAbstracPhoneBuilder具体建造者(Concrete BuilderPhoneBuilder创建的东西细节复杂还必须暴露给使用者。屏蔽过程而不屏蔽细节将复杂对象的构建过程分离出来使得同样的构建过程可以创建不同的表示//产品角色publicclassPhone{protectedStringcpu;protectedStringmem;protectedStringdisk;protectedStringcam;OverridepublicStringtoString(){returnPhone{cpucpu\, memmem\, diskdisk\, camcam\};}publicStringgetCpu(){returncpu;}publicStringgetMem(){returnmem;}publicStringgetDisk(){returndisk;}publicStringgetCam(){returncam;}}//抽象建造者publicabstractclassAbstractBuilder{Phonephone;abstractAbstractBuildercustomCpu(Stringcpu);abstractAbstractBuildercustomMem(Stringmem);abstractAbstractBuildercustomDisk(Stringdisk);abstractAbstractBuildercustomCam(Stringcam);PhonegetProduct(){returnphone;}}//具体建造者publicclassXiaomiBuilderextendsAbstractBuilder{publicXiaomiBuilder(){phonenewPhone();}/** * param cpu */OverrideAbstractBuildercustomCpu(Stringcpu){phone.cpucpu;returnthis;}OverrideAbstractBuildercustomMem(Stringmem){phone.memmem;returnthis;}OverrideAbstractBuildercustomDisk(Stringdisk){phone.diskdisk;returnthis;}OverrideAbstractBuildercustomCam(Stringcam){phone.camcam;returnthis;}}lambok提供的简单方法Phone类上加上BuilderPhonebuildPhone.builder().cpu(1).mem(2).cam(3).disk(4).build();