🌐 设计模式及源码分析(二)

三、创建型模式的作用

3.2原型(Prototype)模式

每一个高可用的框架都是设计模式嵌套使用,而不是单个使用

本体给外部提供一个克隆进行使用,这时候本体就是原型 ,这种方式可以避免重复创建相同的对象,提高了性能和效率。

就比如从数据库查询数据,每次查询的数据都一样,这时候就多次查询的数据就很占用空间,我们一般可以用Redis进行缓存如果查询条件一样就从缓存读取。

原型模式的代码实现

1.建立 Dog 类提供了clone()方法

java 复制代码
/**
 * 当前对象是可克隆的
 */
public class Dog implements Cloneable {

    private String dogName;
    private Integer age;

    public Dog() {
        System.out.println("创建了Dog对象");
    }

    public String getDogName() {
        return dogName;
    }

    public void setDogName(String dogName) {
        this.dogName = dogName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "dogName='" + dogName + ''' +
                ", age=" + age +
                '}';
    }


   //再创建一只狗,赋予所有属性
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Dog dog = new Dog();
        dog.setDogName(dogName);
        dog.setAge(age);
        return dog;
    }
}

2.建立DogData 类:(模拟从数据库拿数据)

java 复制代码
public class DogData {

    //缓存user.序列化和反序列化-深克隆
    private Map<String, Dog> dogCache = new HashMap<>();

    /**
     * 从数据库查数据
     * @return
     */
    public Dog getUser(String username) throws Exception {
        Dog dog = null;
        //缓存中没有
        if(!dogCache.containsKey(username)){
            //查询数据库
            dog = getUserFromDb(username);
        }else {
            //从缓存中直接拿,脏缓存问题
            //原型已经拿到,但是不能直接给。(
            dog = dogCache.get(username);
            System.out.println("从缓存中拿到的是:"+ dog);
            //从这个对象快速得到一个克隆体 == 原型模式
            dog = (Dog) dog.clone();
        }

        return dog;
    }

    private Dog getUserFromDb(String username) throws Exception{
        System.out.println("从数据库查到:"+username);
        Dog dog = new Dog();
        dog.setDogName(username);
        dog.setAge(18);
        //给缓存中放一个clone
        dogCache.put(username, (Dog) dog.clone());
        return dog;
    }


}

3.建立DogTest

Java 复制代码
public class DogTest {

    public static void main(String[] args) throws Exception {
        DogData dogData = new DogData();

        //得到的是克隆体
        Dog 泰迪 = dogData.getUser("泰迪");
        System.out.println("1==>"+泰迪);
        泰迪.setDogName("泰迪副本");
        System.out.println("泰迪自己改了:"+泰迪);


        //得到的是克隆体
        Dog 金毛 = dogData.getUser("泰迪");
        System.out.println("2-->"+金毛);

        //得到的是克隆体
        Dog 柯基 = dogData.getUser("泰迪");
        System.out.println("3-->"+柯基);

        //得到的是克隆体
        Dog 柴犬 = dogData.getUser("泰迪");
        System.out.println("4-->"+柴犬);
        System.out.println(泰迪 == 柯基);

    }
}

以上代码就实现了原型模式

泰迪创建了克隆体并放入缓存当中,如果金毛等需要泰迪的数据就从缓存中拿,即使泰迪更改了名字,也不会影响,因为克隆体已存在在缓存当中,不再改变

3.3工厂(Factory)模式

工厂模式是一种用于管理对象创建的设计模式,可以提高代码的可扩展性和可维护性

1.简单工厂(Simple Factory )

简单工厂中有三个角色

  • Factory:工厂角色, ChinaSimpleFactory
  • Product:抽象产品角色,AbstractPhone
  • ConcreteProduct:具体产品角色, HuaWeiPhoneXiaoMiPhone

1.建立 AbstractPhone(抽象类,定义了一个品牌变量和一个抽象方法)

java 复制代码
public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiPhone 类:(继承抽象类,并实现其中的方法,生产华为手机)

Java 复制代码
public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        this.brand = "华为手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--》数智世界 一触即达");
    }
}

3.建立XiaoMiPhone 类:(继承抽象类,并实现其中的方法,生产小米手机)

Java 复制代码
public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--> 遥遥领先");
    }
}

4.建立ChinaSimpleFactory 类:(一个简单的工厂,用来管理各个产品)

Java 复制代码
public class ChinaSimpleFactory {

    /**
     *
     * @param type  Class: 好像具有扩展性,但是没有解决实际问题
     * @return
     */
    public AbstractPhone newCar(String type){

        //核心方法:一切从简
        if("HuaWei".equals(type)){
            // 钣金、喷漆、放发动机、申请环保

            return new HuaWeiPhone();
        }else if("XiaoMi".equals(type)){
            return new XiaoMiPhone();
        }

        //.....

        return null;
    }
}

5.建立MainTest测试

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        ChinaSimpleFactory factory = new ChinaSimpleFactory();

        AbstractPhone huaWei = factory.newCar("HuaWei");
        AbstractPhone xiaoMi = factory.newCar("XiaoMi");
        huaWei.make();
        xiaoMi.make();

    }
}

简单工厂的缺点

如果有更多的品牌手机,在工厂中就需要添加更多的if else 代码,违反开闭原则。应该直接扩展出一个类来造

2.工厂方法(Factory Method)

工厂方法有四个角色

  • Product:抽象产品 AbstractPhone
  • ConcreteProduct:具体产品 HuaWeiPhone、XiaoMiPhone
  • Factory:抽象工厂 AbstractPhoneFactory
  • ConcreteFactory:具体工厂 HuaWeiPhoneFactory、XiaoMiPhoneFactory

1.建立AbstractPhone(抽象类,定义了一个品牌变量和一个抽象方法)

Java 复制代码
public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiPhone、XiaoMiPhone(继承抽象类,并实现其中的方法,生产华为、小米手机)

Java 复制代码
public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        this.brand = "华为手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"数智世界 一触即达");
    }
}


public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--> 遥遥领先...");
    }
}

3.建立AbstractPhoneFactory (一个手机的抽象类)

csharp 复制代码
public abstract class AbstractPhoneFactory {

    public abstract AbstractPhone newPhone();
    //我能造口罩.....
}

4.建立HuaWeiPhoneFactory、XiaoMiPhoneFactory (华为、小米的工厂类)

Java 复制代码
public class HuaWeiPhoneFactory extends AbstractPhoneFactory {
    @Override
    public AbstractPhone newPhone() {
        return new HuaWeiPhone();
    }
}

public class XiaoMiPhoneFactory extends AbstractPhoneFactory {
    @Override
    public AbstractPhone newPhone() {
        return new XiaoMiPhone();
    }
}

5.建立测试类MainTest

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        AbstractPhoneFactory phoneFactory = new XiaoMiPhoneFactory();
        AbstractPhone abstractXiaoMiPhone = phoneFactory.newPhone();
        abstractXiaoMiPhone.make();
        
        phoneFactory = new HuaWeiPhoneFactory();
        AbstractPhone abstractHuaWeiPhone = phoneFactory.newPhone();
        abstractHuaWeiPhone.make();
    }
}

工厂方法实现了面向接口编程,当然缺点就是:当系统复杂度增加时,工厂方法的品类过于单一,就比如华为和小米不仅要造手机,当要造汽车的时候就很难去优化了

3.抽象工厂(Abstract Factory)

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

它将具体产品的创建与使用分离,使得系统更加灵活和可扩展。当需要添加新的产品类型时,只需要实现新的具体工厂类,而不需要修改使用这些产品的其他部分。

1.建立AbstractCarAbstractPhone 抽象类 (定义了汽车名字,汽车制造方法,手机名字,手机自造方法)

Java 复制代码
public abstract class AbstractCar {

    String carName;
    public abstract void run();
}


public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiCar、HuaWeiPhone、XiaoMiCar、XiaoMiPhone (实现制造手机和汽车)

Java 复制代码
public class HuaWeiCar extends AbstractCar {
    public HuaWeiCar(){
        this.carName = "华为汽车";
    }

    @Override
    public void run() {
        System.out.println(carName +"数智世界 一触即达");
    }
}

public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        brand = "华为";
    }
    @Override
    public void make() {
        System.out.println("数智世界 一触即达");
    }
}

public class XiaoMiCar extends AbstractCar {

    public XiaoMiCar(){
        this.carName = "小米汽车";
    }
    @Override
    public void run() {
        System.out.println(carName +"遥遥领先");
    }
}

public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米";
    }

    @Override
    public void make() {
        System.out.println("瑶瑶领先");
    }
}

3.建立 ChinaFactory (定义了汽车、手机制造两个抽象方法)

java 复制代码
public abstract class ChinaFactory {

    abstract AbstractCar newCar();
    abstract AbstractPhone newPhone();
}

4.建立ChinaPhoneFactory 、ChinaCarFactory (定义了汽车、手机制造中的一个方法)

Java 复制代码
public  abstract  class ChinaCarFactory extends ChinaFactory {
    @Override
    abstract  AbstractCar newCar();

    @Override
    AbstractPhone newPhone() {
        return null;
    }
}


public abstract class ChinaPhoneFactory extends ChinaFactory {
    @Override
    AbstractCar newCar() {
        return null;
    }

    abstract AbstractPhone newPhone();
}

5.建立ChinaHuaWeiCarFactory、ChinaHuaWeiPhoneFactory、ChinaXiaoMiCarFactory、ChinaXiaoMiPhoneFactory (实现各种品牌的手机、汽车制造工厂)

Java 复制代码
public class ChinaHuaWeiCarFactory extends ChinaCarFactory {
    @Override
    AbstractCar newCar() {
        return new HuaWeiCar();
    }

}

public class ChinaHuaWeiPhoneFactory extends ChinaPhoneFactory {

    @Override
    AbstractPhone newPhone() {
        return new HuaWeiPhone();
    }
}

public class ChinaXiaoMiCarFactory extends ChinaCarFactory {
    @Override
    AbstractCar newCar() {
        return new XiaoMiCar();
    }
}

public class ChinaXiaoMiPhoneFactory extends ChinaPhoneFactory {

    @Override
    AbstractPhone newPhone() {
        return new XiaoMiPhone();
    }
}

6.建立测试类MainTest

Java 复制代码
public class MainTest {

    public static void main(String[] args) {

        //

        ChinaFactory chinaFactory = new ChinaXiaoMiPhoneFactory();
        AbstractPhone xiaoMiPhone = chinaFactory.newPhone();
        xiaoMiPhone.make();

        chinaFactory =new ChinaXiaoMiCarFactory();
        AbstractCar xiaoMiCar = chinaFactory.newCar();
        xiaoMiCar.run();


        chinaFactory = new ChinaHuaWeiPhoneFactory();
        AbstractPhone huaWeiPhone = chinaFactory.newPhone();
        huaWeiPhone.make();

        chinaFactory = new ChinaHuaWeiCarFactory();
        AbstractCar huaWeiCar = chinaFactory.newCar();
        huaWeiCar.run();
    }
}

以上代码就实现了抽象工厂,虽然刚开始需要建立很多的抽象类,还有抽象工厂,但是后面扩展很方便,系统需要增强新的功能只需要建立相应的抽象、抽象工厂、实现类即可

3.4 建造者(Builder)模式

建造者模式中三个角色

  • 产品角色(Product):Phone
  • 抽象建造者(Builder):AbstractBuilder
  • 具体建造者(Concrete Builder):XiaomiBuilder

1.建立 Phone(定义了一个手机类包含了各种参数)

java 复制代码
@Builder
@ToString
public class Phone {

    protected String cpu;
    protected String mem;
    protected String disk;
    protected String cam;
    
}

2.建立 AbstractBuilder 抽象类 (定义了制造手机参数方法的抽象类)

Java 复制代码
public abstract class AbstractBuilder  {

    Phone phone;
    abstract AbstractBuilder makeCpu(String cpu);
    abstract AbstractBuilder makeMem(String mem);
    abstract AbstractBuilder makeDisk(String disk);
    abstract AbstractBuilder makeCam(String cam);

    Phone getProduct(){
        return phone;
    }
}

3.建立XiaomiBuilder(实现了抽象类中的方法)

typescript 复制代码
public class XiaomiBuilder  extends AbstractBuilder{


    public XiaomiBuilder(){
        phone = Phone.builder().build();
    }

   
    @Override
    AbstractBuilder makeCpu(String cpu) {
        phone.cpu = cpu;
        return this;
    }

    @Override
    AbstractBuilder makeMem(String mem) {
        phone.mem = mem;
        return this;
    }

    @Override
    AbstractBuilder makeDisk(String disk) {
        phone.disk = disk;
        return this;
    }

    @Override
    AbstractBuilder makeCam(String cam) {
        phone.cam = cam;
        return this;
    }
}

4.建立测试类MainTest

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        AbstractBuilder builder = new XiaomiBuilder();
        //链式建造者
        Phone phone = builder.makeCpu("骁龙8个8")
                .makeCam("2亿")
                .makeDisk("1T")
                .makeMem("16G")
                .getProduct();
        System.out.println(phone);

        //lombok提供的建造模式
        Phone build = Phone.builder()
                .cpu("1亿")
                .mem("2T")
                .cam("3G")
                .build();
        System.out.println(build);


    }
}
相关推荐
ok!ko2 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2401_857622662 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589362 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
拉里小猪的迷弟3 小时前
设计模式-创建型-常用:单例模式、工厂模式、建造者模式
单例模式·设计模式·建造者模式·工厂模式
哎呦没3 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch4 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
严文文-Chris5 小时前
【设计模式-中介者模式】
设计模式·中介者模式
刷帅耍帅5 小时前
设计模式-中介者模式
设计模式·中介者模式
杨哥带你写代码5 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
刷帅耍帅5 小时前
设计模式-组合模式
设计模式·组合模式