原型模式与建造者模式

2020-06-27  本文已影响0人  攻城老狮

原型模式与建造者模式

参考教程:https://www.bilibili.com/video/BV1G4411c7N4
代码实现 Github:https://github.com/yaokuku123/pattern


原型模式

  1. 案例

现在有一只羊tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和tom羊属性完全相同的10只羊。

  1. 传统方法
4.png
package com.yqj.pattern.prototype.traditional;

public class Sheep {
    private String name;
    private int age;
    private String color;

    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}
package com.yqj.pattern.prototype.traditional;

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("tom", 1, "白色");
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
    }
}

传统方法虽然可以实现相应的功能,但存在问题:不能动态的获取对象运行时的状态,而只是从初始化的对象中获取参数;若原对象增减属性的话,所有依此创建的新对象均需要修改;在创建新对象的时候,总是需要获取原始对象的属性,若对象的属性复杂时,效率低。

  1. 原型模式

解释:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。,允许一个对象再创建另外一个可定制的对象, 无需知道如何创建的细节。

原理:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即:对象.clone()

  1. 改进代码
package com.yqj.pattern.prototype.improve;

public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;

    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }

    @Override
    protected Object clone() {
        Object sheep = null;
        try {
            sheep = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return sheep;
    }
}
package com.yqj.pattern.prototype.improve;

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("tom", 1, "白色");
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        System.out.println(sheep+" hashcode:"+sheep.hashCode());
        System.out.println(sheep2+" hashcode:"+sheep2.hashCode());
        System.out.println(sheep3+" hashcode:"+sheep3.hashCode());

    }
}
  1. 深拷贝和浅拷贝

对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类 的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内 存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个 实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成 员变量值

浅拷贝是使用默认的 clone()方法来实现 sheep = (Sheep) super.clone();

复制对象的所有基本数据类型的成员变量值

为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变 量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对 整个对象进行拷贝

深拷贝实现方式1:重写clone方法来实现深拷贝

深拷贝实现方式2:通过对象序列化实现深拷贝(推荐)

建造者模式

  1. 案例

盖房子项目:

  1. 传统方法
1-1592357505036.png
package com.yqj.pattern.builder.traditional;
//抽象房子类
abstract class AbstractHouse {
    public abstract void buildBasic();
    public abstract void buildWalls();
    public abstract void roofed();
    public void build(){
        buildBasic();
        buildWalls();
        roofed();
    }
}
//普通房子
class CommonHouse extends AbstractHouse{

    @Override
    public void buildBasic() {
        System.out.println("普通房子打地基");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子刷墙");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子封顶");
    }
}
//别墅
class HighBuilding extends AbstractHouse{

    @Override
    public void buildBasic() {
        System.out.println("别墅打地基");
    }

    @Override
    public void buildWalls() {
        System.out.println("别墅刷墙");
    }

    @Override
    public void roofed() {
        System.out.println("别墅封顶");
    }
}
//用户
public class Client{
    public static void main(String[] args) {
        CommonHouse commonHouse = new CommonHouse();
        commonHouse.build();

        HighBuilding highBuilding = new HighBuilding();
        highBuilding.build();
    }
}

设计的程序结构,过于简单,没有设计缓存层对象,程序的扩展和维护不好. 也就 是说,这种设计方案,把产品(即:房子) 和 创建产品的过程(即:建房子流程) 封装在一起,耦合性增强了。应该想办法将产品和过程分离,达到解耦的目的。

  1. 建造者模式

解释:它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

建造者模式的四个角色:

  1. 改进方法
1-1592362117625.png
package com.yqj.pattern.builder.improve;

//产品
class House{
    private String basic;
    private String wall;
    private String roofed;

    public String getBasic() {
        return basic;
    }

    public void setBasic(String basic) {
        this.basic = basic;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getRoofed() {
        return roofed;
    }

    public void setRoofed(String roofed) {
        this.roofed = roofed;
    }

    @Override
    public String toString() {
        return "House{" +
                "basic='" + basic + '\'' +
                ", wall='" + wall + '\'' +
                ", roofed='" + roofed + '\'' +
                '}';
    }
}

//抽象建造者
abstract class HouseBuilder{
    protected House house = new House();
    //建造流程,定义有关的抽象方法
    public abstract void buildBasic();
    public abstract void buildWalls();
    public abstract void roofed();
    //建造好房子,返回产品
    public House buildHouse(){
        return house;
    }
}

//具体建造者1
class CommonHouseBuilder extends HouseBuilder{
    //实现具体的构建方法
    @Override
    public void buildBasic() {
        house.setBasic("普通房子打地基");
    }

    @Override
    public void buildWalls() {
        house.setWall("普通房子刷墙");
    }

    @Override
    public void roofed() {
        house.setRoofed("普通房子封顶");
    }
}

//具体建造者2
class HighBuilding extends HouseBuilder{

    @Override
    public void buildBasic() {
        house.setBasic("别墅打地基");
    }

    @Override
    public void buildWalls() {
        house.setWall("别墅刷墙");
    }

    @Override
    public void roofed() {
        house.setRoofed("别墅封顶");
    }
}



//指挥者
class HouseDirector{
    HouseBuilder houseBuilder;

    public HouseDirector(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    //制定产品的构建流程
    public House build(){
        houseBuilder.buildBasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        //返回产品
        return houseBuilder.buildHouse();
    }
}

//用户
public class Client{
    public static void main(String[] args) {
        HouseDirector director = new HouseDirector(new CommonHouseBuilder());
        System.out.println(director.build());
        //更改指挥者的构建产品
        director.setHouseBuilder(new HighBuilding());
        System.out.println(director.build());
    }
}
  1. 小结
上一篇下一篇

猜你喜欢

热点阅读