设计模式全详解

您所在的位置:网站首页 设计策略有哪几种 设计模式全详解

设计模式全详解

2024-07-10 00:18| 来源: 网络整理| 查看: 265

本文是学习设计模式后,自己做的笔记。

学习资源有菜鸟教程以及尚硅谷韩顺平图解设计模式。

文章目录 1 单例模式概述:特点:适用范围:1.1 饿汉式静态常量实现特点:实现步骤:代码实现:优缺点分析:静态代码块实现: 1.2 懒汉式特点:步骤:第一种写法: (线程不安全)代码实现:第二种写法: 1.3 双重检查式特点:步骤:代码实现: 1.4 静态内部类特点:步骤:代码实现: 1.5 枚举特点:步骤:代码实现: 单例模式注意事项和说明 2 工厂模式概述:特点:类图示例步骤代码实现优缺点分析:2.1 工厂方法模式:概述:特点:代码实现:优缺点分析 3 抽象工厂模式概述:特点:类图示例:步骤代码实现:优缺点分析:工厂模式小结: 4 原型模式概述:特点:第一种:浅拷贝步骤代码实现:第二种:深拷贝代码实现优缺点分析:原型模式的注意事项和细节 5 建造者模式(Builder)概述:特点:主要角色:类图示例:步骤代码实现:优缺点分析:变形建造者模式: 代码实现:

1 单例模式 概述:

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,保证在整个的软件中,该类只创建一个对象实例。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式有八种方式:

饿汉式(静态常量);饿汉式(静态代码块);懒汉式(线程不安全);懒汉式(线程安全,同步方法);懒汉式(线程安全,同步代码块);双重检查(使用锁和volatile关键字);静态内部类;枚举 特点:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

适用范围: 1.1 饿汉式 静态常量实现 特点:

在类加载时便实例化对象。

是最简单的一种实现方法。

实现步骤:

1、构造器私有化

2、类的内部创建类对象

3、向外暴露一个静态获取对象的方法

代码实现:

第一种:

public class SingletonTest01 { public static void main(String[] args) { //测试 Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } //饿汉式(静态变量) class Singleton { //1. 构造器私有化, 外部不能new private Singleton() { } //2.本类内部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } } 优缺点分析:

优点:

写法比较简单,在类装载时便完成实例化,避免了线程同步问题。

缺点:

在类装载的时候就完成实例化,没有达到懒装载的效果,如果从未使用这个实例,就会造成内存的浪费。

这种方式基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,在单例模式中大多数都是调用 getInstance 方法,但是导致类装载的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 就没有达到 lazy loading 的效果

结论:

可用,但是可能造成内存浪费。

静态代码块实现:

代码演示:

public class SingletonTest02 { public static void main(String[] args) { //测试 Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } //饿汉式(静态变量) class Singleton { //1. 构造器私有化, 外部能new private Singleton() { } //2.本类内部创建对象实例 private static Singleton instance; static { // 在静态代码块中,创建单例对象 instance = new Singleton(); } //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }

优缺点对比:

这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。结论:这种单例模式可用,但是可能造成内存浪费 1.2 懒汉式 特点:

在类被使用时才会实例化对象。

步骤:

1、构造器私有化

2、类的内部创建类对象,并在调用getInstance方式时实例化对象。

3、向外暴露一个静态获取对象的方法

第一种写法: (线程不安全)

多线程时可能造成多实例化。

代码实现: public class SingletonTest03 { public static void main(String[] args) { System.out.println("懒汉式1 , 线程不安全~"); Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } class Singleton { private static Singleton instance; private Singleton() {} //提供一个静态的公有方法,当使用到该方法时,才去创建 instance //即懒汉式 public static Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } } 第二种写法:

(线程安全,同步方法)

效率低,多线程时依旧可能造成实例化。

public class SingletonTest04 { public static void main(String[] args) { System.out.println("懒汉式2 , 线程安全~"); Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } // 懒汉式(线程安全,同步方法) class Singleton { private static Singleton instance; private Singleton() {} //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题 //即懒汉式 public static synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } } 1.3 双重检查式 特点:

实现懒加载,并解决线程同步问题。

步骤:

1、构造器私有化

2、类的内部创建类对象但不实例化对象。

3、向外暴露一个静态获取对象的方法,方法中判空中同步代码块(对应类),并在同步代码块中再次判空。

代码实现: public class SingletonTest06 { public static void main(String[] args) { System.out.println("双重检查"); Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } // 懒汉式(线程安全,同步方法) class Singleton { private static volatile Singleton instance; //使用volatile 轻量级同步机制 private Singleton() {} //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题 //同时保证了效率, 推荐使用 public static synchronized Singleton getInstance() { //第一重检查 if(instance == null) { synchronized (Singleton.class) { //第二重检查 if(instance == null) { instance = new Singleton(); } } } return instance; } } 1.4 静态内部类 特点:

利用静态内部类被调用时才初始化实例的特点,在类的内部创建一个静态内部类,并且在内部类中实例化对象,用final关键词来修饰(提升性能)。

步骤:

1、构造器私有化

2、在类中创建一个静态内部类,在静态内部类类的内部创建并类实例化对象。

3、向外暴露一个静态获取对象的方法

代码实现: public class SingletonTest07 { public static void main(String[] args) { System.out.println("使用静态内部类完成单例模式"); Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } } // 静态内部类完成, 推荐使用 class Singleton { private static volatile Singleton instance; //构造器私有化 private Singleton() {} //写一个静态内部类,该类中有一个静态属性 Singleton private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE public static synchronized Singleton getInstance() { return SingletonInstance.INSTANCE; } } 1.5 枚举 特点:

应用枚举类型(enum)来实现,是最简单有效的方法,是effective java作者推荐适用的方法。

步骤:

创建一个枚举类实例,加一个INSTANCE关键词即可。

在类中完成各种方法的适用。

代码实现:

优点:

不但懒加载,还可以防止反序列化创建新对象。

public class SingletonTest08 { public static void main(String[] args) { Singleton instance = Singleton.INSTANCE; Singleton instance2 = Singleton.INSTANCE; System.out.println(instance == instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); instance.sayOK(); } } //使用枚举,可以实现单例, 推荐 enum Singleton { INSTANCE; //属性 public void sayOK() { System.out.println("ok~"); } } 单例模式注意事项和说明 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session 工厂等) 2 工厂模式 概述:

一种在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象的设计模式。

特点:

将类创建封装起来,不会对客户端暴露创建逻辑,通过使用一个共同的接口来指向创建新的对象。

但是当在增加新的类型时,违反开闭原则。

类图示例

工厂方法模式类图

步骤代码实现 创建一个抽象接口 // 创建一个抽象接口 public interface Shape { void draw(); } //主测试类 public class test { public static void main(String[] args) { shapeFactory shapefactory = new shapeFactory(); shapefactory.getShape("circle").draw(); shapefactory.getShape("square").draw(); shapefactory.getShape("rectangle").draw(); } } 创建接口实现类: //创建各个实体类 public class Square implements Shape{ public void draw() { System.out.println(" 画了一个正方形!"); } } public class Square implements Shape{ public void draw() { System.out.println(" 画了一个正方形!"); } } public class Rectangle implements Shape{ @Override public void draw() { System.out.println(" 画了一个长方形!"); } } public class Circle implements Shape{ @Override public void draw() { // TODO Auto-generated method stub System.out.println(" 画了一个圆圈!"); } } 创建工厂类用与创建对象,并返回对象 在这里就将内部生产对象的逻辑进行封装,不对外暴露 //创建工厂类用与创建对象,并返回对象 public class shapeFactory { public Shape getShape(String type) { if(type == null) return null; if(type.equalsIgnoreCase("circle")) { return new Circle(); }else if (type.equalsIgnoreCase("rectangle")) { return new Rectangle(); }else if(type.equalsIgnoreCase("Square")) { return new Square(); } else return null; } } 优缺点分析:

优点:

一个调用者想创建一个对象,只要知道其名称就可以了。

扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:

每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加

再增加类时会违反开闭原则(对已经写好的类进行了修改)

2.1 工厂方法模式: 概述:

一种可以解决多种类组合创建的工厂模式

特点:

定义一个创建对象的抽象方法,由子类决定要实例化的类,将对象的实例化推迟到子类。对工厂进行再一次分类。

代码实现: // 接口机器方法 public interface MachineApi { //process:加工 material:材料 public void process(String material); } //对接口的实现 /** * 馒头机器 * steamed bun : 馒头 */ public class SteamedBunMachine implements MachineApi { @Override public void process(String material) { System.out.println("我把" + material + "加工成了馒头"); } } /** * 面条机器 * noodle : 面条 */ public class BoodleMachine implements MachineApi { @Override public void process(String material) { System.out.println("我把" + material + "加工成了面条"); } } //抽象工厂实现 public abstract class Factory{ /** * 让子类(具体工厂)来实例化具体对象(机器) */ public abstract MachineApi newMachine(); /** * 加工材料 */ public void process(String material){ MachineApi machine = newFileApi(); machine.process(material); } } //子类实例化工厂 //馒头工厂 public class SteamedBunFactory extends Factory{ //馒头工厂,只需要提供馒头机器就行 @Override public MachineApi newMachine() { return new SteamedBunMachine(); } } //面条工厂 public class NoodleFactory extends Factory{ //面条工厂,只需要提供面条机器就行 @Override public MachineApi newMachine() { return new BoodleMachine(); } } // 主程序使用 SteamedBunFactory mSteamedBunFactory = new SteamedBunFactory (); mSteamedBunFactory.process("面粉");//我把面粉加工成了馒头 优缺点分析

优点: 在拥有工厂方法的优点下还解决了扩展时候的开闭原则违反问题。

缺点:依旧是会导致类过多,系统复杂度增加的问题。

3 抽象工厂模式 概述: 抽象工厂模式定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。 特点:

可以将简单工厂模式跟工厂方法模式进行整合,可以理解为对简单工厂模式的改进。

抽象工厂模式将工厂抽象成两层,抽象工厂以及具体实现的工厂类,可以根据创建的而对象类型来使用对应的工厂子类,将单个工厂变成工厂簇。

类图示例:

抽象工厂模式示例

步骤代码实现: 为形状创建一个接口 //1、为形状创建一个接口 public interface Shape { void draw(); }

2. 创建形状接口的实体类

//2、创建形状接口的实体类 public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } } 为颜色创建接口 //3、为颜色创建接口 public interface Color { void fill(); } 创建颜色接口的实体类 //4、创建颜色接口的实体类 public class Red implements Color { @Override public void fill() { System.out.println("Inside Red::fill() method."); } } public class Green implements Color { @Override public void fill() { System.out.println("Inside Green::fill() method."); } } public class Blue implements Color { @Override public void fill() { System.out.println("Inside Blue::fill() method."); } } 为两种类创建抽象工厂 //5、为两种类创建抽象工厂类来获取工厂 public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ; } 创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。 //6、创建实体工厂 public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } } public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); } else if(color.equalsIgnoreCase("GREEN")){ return new Green(); } else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } } 创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂 //7、创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂 public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } } 使用 //8、使用 public class AbstractFactoryPatternDemo { public static void main(String[] args) { //获取形状工厂 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //获取形状为 Circle 的对象 Shape shape1 = shapeFactory.getShape("CIRCLE"); //调用 Circle 的 draw 方法 shape1.draw(); //获取形状为 Rectangle 的对象 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw(); //获取形状为 Square 的对象 Shape shape3 = shapeFactory.getShape("SQUARE"); //调用 Square 的 draw 方法 shape3.draw(); //获取颜色工厂 AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //获取颜色为 Red 的对象 Color color1 = colorFactory.getColor("RED"); //调用 Red 的 fill 方法 color1.fill(); //获取颜色为 Green 的对象 Color color2 = colorFactory.getColor("Green"); //调用 Green 的 fill 方法 color2.fill(); //获取颜色为 Blue 的对象 Color color3 = colorFactory.getColor("BLUE"); //调用 Blue 的 fill 方法 color3.fill(); } } 优缺点分析:

优点:

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:

产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

工厂模式小结: 工厂模式的意义 将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项 目的扩展和维护性。三种工厂模式 :简单工厂模式、工厂方法模式、抽象工厂模式设计模式的依赖抽象原则 创建对象实例时,不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。不要让类继承具体类,而是继承抽象类或者是实现 interface(接口)不要覆盖基类中已经实现的方法。 4 原型模式 概述: 原型模式(Prototype 模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节,同时又能保证性能工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone() 特点:

实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。

利用已有的一个原型对象,快速地生成和原型对象一样的实例。适用于需要重复创建多个对象的需求。

具体有三个角色:

1、原型角色(复写cloneable接口)

2、具体原型角色

3、使用者角色

第一种:浅拷贝

对于是基本类型的数据成员进行值传递,对于是引用数据类型的进行引用传递,即对一个引用类型进行修改,另一个对象也会改变。

直接复写clone方法即可。

步骤代码实现:

1、创建Shape类并复写clone方法

//1、创建Shape类并复写clone方法 public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { //复写并使用父类构造方法,获取异常 Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } } 使用 //2、使用: public class test { public static void main(String[] args) { // TODO Auto-generated method stub concreteShape shape =new concreteShape(); concreteShape shape2 = null; shape2 = (concreteShape)shape.clone(); //(调用后要进行对象转型) } } 第二种:深拷贝

深拷贝解决了浅拷贝中对引用对象的完全复制,类似对引用对象进行new的创建。

有两种解决方法

递归调用clone方法

序列化与反序列化

代码实现 //实现Serializable接口,用序列化跟反序列化克隆对象 public class Shape implements Serializable{ private String id; protected String type; public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { //创建流对象 ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { //进行序列化 bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); //当前对象以对象流输出出去 //反序列化 bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); Shape copyShape = (Shape)ois.readObject(); return copyShape; }catch(Exception e) { e.printStackTrace(); return null; }finally { try { bos.close(); bis.close(); oos.close(); ois.close(); }catch(Exception e2) { System.out.println(e2); } } } } 优缺点分析:

优点:

1、性能提高。

2、逃避构造函数的约束。

缺点:

1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

2、必须实现 Cloneable 接口。

原型模式的注意事项和细节 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率不用重新初始化对象,而是动态地获得对象运行时的状态如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码在实现深克隆的时候可能需要比较复杂的代码缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了 ocp 5 建造者模式(Builder) 概述:

是一种对象构建模式,可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

建造者模式使用户可以一步步创建一个复杂的对象。它允许用户只通过指定复杂对象的类型和内容就可以构建他们,而不需要知道内部的具体细节。

特点:

与工厂模式相比更加倾向于过程的组合建造

主要角色:

产品角色:一个具体的产品对象

抽象建造者:创建一个产品角色对象的各个部件指定的接口或者抽象类。

具体建造者:实现接口,构建和装配各个部件。

指挥者:构建一个使用抽象建造者接口的对象,用于创建一个复杂的对象。主要可以隔离客户与对象的生产过程,并且负责控制产品对象的生产过程。

类图示例:

建造者模式类图示例

步骤代码实现:

此例中产品为房子:

创建产品类 //1、房子对象类 public class House { private String baise; private String wall; private String roofed; public String getBaise() { return baise; } public void setBaise(String baise) { this.baise = baise; } 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; } } 创建抽象产品建造者类 //2、抽象房子建造者类 //抽象的建造者 public 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; } } 创建建造者实体类 //3、房子建造者实体类 public class HighBuilder { public class HighBuilding extends HouseBuilder { @Override public void buildBasic() { // TODO Auto-generated method stub System.out.println(" 高楼的打地基100米 "); } @Override public void buildWalls() { // TODO Auto-generated method stub System.out.println(" 高楼的砌墙20cm "); } @Override public void roofed() { // TODO Auto-generated method stub System.out.println(" 高楼的透明屋顶 "); } } } public class CommonHouse extends HouseBuilder { @Override public void buildBasic() { // TODO Auto-generated method stub System.out.println(" 普通房子打地基5米 "); } @Override public void buildWalls() { // TODO Auto-generated method stub System.out.println(" 普通房子砌墙10cm "); } @Override public void roofed() { // TODO Auto-generated method stub System.out.println(" 普通房子屋顶 "); } }

4、创建造指挥者类(用于具体化建造流程)

//4、建造指挥者类(用于具体化建造流程) //指挥者,这里去指定制作流程,返回产品 public class HouseDirector { HouseBuilder houseBuilder = null; //构造器传入 houseBuilder public HouseDirector(HouseBuilder houseBuilder) { this.houseBuilder = houseBuilder; } //通过setter 传入 houseBuilder public void setHouseBuilder(HouseBuilder houseBuilder) { this.houseBuilder = houseBuilder; } //如何处理建造房子的流程,交给指挥者 public House constructHouse() { houseBuilder.buildBasic(); houseBuilder.buildWalls(); houseBuilder.roofed(); return houseBuilder.buildHouse(); } } 客户端调用 5、客户端调用 public class Client { public static void main(String[] args) { House house = new HouseDirector(new CommonHouse()).constructHouse(); HouseDirector houseDirector = new HouseDirector(new CommonHouse()); houseDirector.setHouseBuilder(new HighBuilding()); house = houseDirector.constructHouse(); } } 优缺点分析:

优点:

建造者独立,易扩展。

便于控制细节风险。

缺点:

产品必须有共同点,范围有限制。

如内部变化复杂,会有很多的建造类。

变形建造者模式:

可以在用户对实体类的创建有多种不同的类型需求,例如存在必须的主要属性,并且其他的属性可以填也可以不填,此时传统的构造多种构造器的方法不再实用。

基本解决思路:

在实体类中创建一个静态内部类,静态内部类持有所有的实体类属性。

将实体类的构造器私有化,并且传入Builder静态内部类,用Builder类中的已经完成赋值的对实体类属性进行赋值。

在Builder中用一个build()方法返回一个新的实体类,用于实体类的实体化。舍去了指导者的角色。将这个角色放在类中。

优点:

可以使类的创建更加自由,并且在Buider中的构造器可以对类的必须属性进行约束,可以满足多种多样的创建类需求。在android开发中的很多组件都是用到该思想。

代码实现: public class Person { /*名字(必须)*/ private final String name; /*性别(必须)*/ private final String gender; /*年龄(非必须)*/ private final String age; /*鞋子(非必须)*/ private final String shoes; /*衣服(非必须)*/ private final String clothes; /*钱(非必须)*/ private final String money; /*房子(非必须)*/ private final String house; /*汽车(非必须)*/ private final String car; /*职业(非必须)*/ private final String career; //私有化构造方法,用builder的属性来进行赋值。 private Person(Builder builder) { this.name = builder.name; this.gender = builder.gender; this.age = builder.age; this.shoes = builder.shoes; this.clothes = builder.clothes; this.money = builder.money; this.house = builder.house; this.car = builder.car; this.career = builder.career; } //静态内部类 public static class Builder { private final String name; private final String gender; private String age; private String shoes; private String clothes; private String money; private String house; private String car; private String career; public Builder(String name,String gender) { this.name = name; this.gender = gender; } //各个属性在赋值后返回一个新的Bulider对象,类似一种动态规划的思想,重复赋值。 public Builder age(String age) { this.age = age; return this; } public Builder car(String car) { this.car = car; return this; } public Builder shoes(String shoes) { this.shoes = shoes; return this; } public Builder clothes(String clothes) { this.clothes = clothes; return this; } public Builder money(String money) { this.money = money; return this; } public Builder house(String house) { this.house = house; return this; } public Builder career(String career) { this.career = career; return this; } //最后用一个build方法来把Person创建完成并返回 public Person build(){ return new Person(this); } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3