23种设计模式(2)
一、建造者模式
1. 适用场景
(1)如果需要创建的各种形式的产品,它们的制造过程相似且仅有细节上的差异。
【1】例如建造房屋,由于不同配置的房屋配置不一样,所以重载了构造器后,依旧会有大部分代码重复部分
class House {
House(int size) { ... }
House(int size, boolean cheese) { ... }
House(int size, boolean cheese, boolean pepperoni) { ... }
// ...
【2】或是一个构造器中注入建造房屋需要的所有参数,当时在使用时,会出现大量参数未使用的情况。
(2)建造者模式可以分步骤生成对象, 而且允许使用必须的步骤。 应用该模式后, 再也不需要将几十个参数塞进构造函数里了。
2. 实现部分
(1)产品 (Products):是最终生成的产品对象。里面包含建造一个产品所需要的所有属性。但是生产出来的每个产品,不一定都用到全部属性。
(2)建造者接口(Builder):声明构造一个产品所需要的所有步骤。以及返回一个产品的方法。可用接口或者抽象类。
(3)具体的建造类 (Concrete Builders):实现Builder接口,提供构造过程的不同实现。注意在该类中实例化一个产品对象。
(4)主管类(Director):定义调用构造产品的步骤顺序。这样就可以创建和复用特定的产品配置。
3. 代码实现
(1)产品:FoodProducts类
package builder_module.demo1;
/**
* @Package: builder_module
* @ClassName: FoodProducts
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/18 16:39
* @Description: 产品 (Products):是最终生成的对象。
* 食物产品
*/
public class FoodProducts {
private String rice;
private String drinks;
private String table;
private int people;
public int getPeople() {
return people;
}
public void setPeople(int people) {
this.people = people;
}
public String getRice() {
return rice;
}
public void setRice(String rice) {
this.rice = rice;
}
public String getDrinks() {
return drinks;
}
public void setDrinks(String drinks) {
this.drinks = drinks;
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
@Override
public String toString() {
return "FoodProductst套餐{" +
"rice='" + rice + '\'' +
", drinks='" + drinks + '\'' +
", table='" + table + '\'' +
", people=" + people +
'}';
}
}
(2)建造者接口:Builder接口
package builder_module.demo1;
/**
* @Package: builder_module
* @ClassName: Builder
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/18 16:25
* @Description: 建造者接口(Builder)
* 声明构造一个产品所需要的所有步骤。
* 干饭人
*/
public interface Builder {
void selectRice(); //选择米饭
void selectDrinks(); //选择饮料
void selectTable(); //选择餐桌
void selectPeople(); //选择就餐人数
FoodProducts getProducts();
}
(3)具体的建造类:work类
package builder_module.demo1;
/**
* @Package: builder_module
* @ClassName: work
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/18 16:52
* @Description: 实现Builder接口
* 厨师
*/
public class work implements Builder {
private FoodProducts foodProducts;
public work() {
foodProducts = new FoodProducts();
}
@Override
public void selectRice() {
foodProducts.setRice("选择米饭");
System.out.println("选择米饭");
}
@Override
public void selectDrinks() {
System.out.println("选择饮料");
foodProducts.setDrinks("选择饮料");
}
@Override
public void selectTable() {
System.out.println("选择桌子");
foodProducts.setTable("选择餐桌");
}
@Override
public void selectPeople() {
System.out.println("选择就餐人数");
foodProducts.setPeople(4);
}
@Override
public FoodProducts getProducts() {
return foodProducts;
}
}
(4)主管类:Director类
package builder_module.demo1;
/**
* @Package: builder_module
* @ClassName: Director
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/18 20:08
* @Description: 指挥类:定义调用构造步骤的顺序
* 前台服务员
*/
public class Director {
// 前台服务员收到干饭人的点餐需求(先选就餐人数,再选桌子,再选米饭,最后选饮料)
// 然后返回一个食品套餐
public FoodProducts build(Builder builder){
builder.selectPeople(); //1.选择就餐人数
builder.selectTable(); //2. 先选桌子
//builder.selectRice(); //3. 再选米饭
builder.selectDrinks(); //4. 最后选饮料
return builder.getProducts();
}
}
(5)测试类
package builder_module.demo1;
/**
* @Package: builder_module
* @ClassName: test
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/18 20:32
* @Description: 测试类
*/
public class test {
public static void main(String[] args) {
//1. 前台服务员
Director director = new Director();
//2. 前台服务员 指挥具体的厨师 建造产品
FoodProducts build = director.build(new work());
System.out.println(build);
}
}
二、原型模式(亦称: 克隆、Clone、Prototype)
1. 作用
能够复制已有对象, 而又无需使代码依赖它们所属的类。
2. 适用场景
当要大量复制一个对象,或者不想创建一个很复杂的对象,可用原型模式
3. 实现
(1)原型接口(Prototype):在其中声明克隆方法。该接口可用使用自带的cloneable接口。
(2)原型类(Concrete Prototype):将实现克隆方法。 将原始对象的数据复制到克隆体中。
【1】浅克隆
【2】深克隆
4. 代码
- 形状的原型接口
package prototype.demo1;
/**
* @Package: prototype
* @ClassName: ShapePrototype
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/22 10:11
* @Description: 形状的原型接口
*/
public interface ShapePrototype {
ShapePrototype clone();
}
- 具体的原型类 —— 矩形
package prototype.demo1;
/**
* @Package: prototype
* @ClassName: RectangleConcretePrototype
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/22 10:14
* @Description: 具体的原型类 —— 矩形
*/
public class RectangleConcretePrototype implements ShapePrototype{
private int x;
private int y;
private String color;
private RectangleConcretePrototype re;
public RectangleConcretePrototype() {
}
public RectangleConcretePrototype(int x, int y, String color) {
this.x = x;
this.y = y;
this.color = color;
}
@Override
public ShapePrototype clone() {
//深克隆
re = new RectangleConcretePrototype();
re.x = this.x;
re.y = this.y;
re.color = this.color;
return re;
//浅克隆
//re = this;
//return re;
}
@Override
public String toString() {
return "x=" + x +
", y=" + y +
", color='" + color + '\'';
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
- 测试类
package prototype.demo1;
/**
* @Package: prototype
* @ClassName: test
* @Author: 爱吃凉拌辣芒果
* @CreateTime: 2022/4/22 10:18
* @Description: 测试类
*/
public class test {
public static void main(String[] args) {
RectangleConcretePrototype prototype =
new RectangleConcretePrototype(1, 2, "黄色");
ShapePrototype clone = prototype.clone();
System.out.println("原型-> "+prototype.hashCode());
System.out.println("克隆-> "+clone.hashCode());
System.out.println("原型-> "+prototype);
System.out.println("克隆-> "+clone);
prototype.setColor("绿色");
System.out.println("原型-> "+prototype);
System.out.println("克隆-> "+clone);
}
}
package prototype.demo1;
public class RectangleConcretePrototype1 implements Cloneable{
private int x;
private int y;
private String color;
@Override
protected Object clone() throws CloneNotSupportedException {
RectangleConcretePrototype1 clone =
(RectangleConcretePrototype1) super.clone();
return clone;
}
public RectangleConcretePrototype1(int x, int y, String color) {
this.x = x;
this.y = y;
this.color = color;
}
@Override
public String toString() {
return "x=" + x +
", y=" + y +
", color='" + color + '\'';
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}