【Java设计模式】1-15章

第1章 内容介绍

1.1 Java设计模式内容介绍

1.1.1 先看几个经典的面试题

1.1.2 设计模式的重要性 

1.2 课程亮点和授课方式

第2章 设计模式七大原则

2.1 设计模式的目的

2.2 设计模式七大原则

2.3 ①单一职责原则

方案1 

package com.atguigu.principle.singleresponsibility;public class SingleResponsibility1 {public static void main(String[] args) {// TODO Auto-generated method stubVehicle vehicle = new Vehicle();vehicle.run("摩托车");vehicle.run("汽车");vehicle.run("飞机");}}// 交通工具类
// 方式1
// 1. 在方式1 的run方法中,违反了单一职责原则
// 2. 解决的方案非常的简单,根据交通工具运行方法不同,分解成不同类即可
class Vehicle {public void run(String vehicle) {System.out.println(vehicle + " 在公路上运行....");}
}

方案2

package com.atguigu.principle.singleresponsibility;public class SingleResponsibility2 {public static void main(String[] args) {// TODO Auto-generated method stubRoadVehicle roadVehicle = new RoadVehicle();roadVehicle.run("摩托车");roadVehicle.run("汽车");AirVehicle airVehicle = new AirVehicle();airVehicle.run("飞机");}}//方案2的分析
//1. 遵守单一职责原则
//2. 但是这样做的改动很大,即将类分解,同时修改客户端
//3. 改进:直接修改Vehicle 类,改动的代码会比较少=>方案3class RoadVehicle {public void run(String vehicle) {System.out.println(vehicle + "公路运行");}
}class AirVehicle {public void run(String vehicle) {System.out.println(vehicle + "天空运行");}
}class WaterVehicle {public void run(String vehicle) {System.out.println(vehicle + "水中运行");}
}

方案3

package com.atguigu.principle.singleresponsibility;public class SingleResponsibility3 {public static void main(String[] args) {// TODO Auto-generated method stubVehicle2 vehicle2  = new Vehicle2();vehicle2.run("汽车");vehicle2.runWater("轮船");vehicle2.runAir("飞机");}
}//方式3的分析
//1. 这种修改方法没有对原来的类做大的修改,只是增加方法
//2. 这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责
class Vehicle2 {public void run(String vehicle) {//处理System.out.println(vehicle + " 在公路上运行....");}public void runAir(String vehicle) {System.out.println(vehicle + " 在天空上运行....");}public void runWater(String vehicle) {System.out.println(vehicle + " 在水中行....");}//方法2.//..//..//...
}

2.4 ②接口隔离原则(Interface Segregation Principle)

package com.atguigu.principle.segregation;public class Segregation1 {public static void main(String[] args) {// TODO Auto-generated method stub}}//接口
interface Interface1 {void operation1();void operation2();void operation3();void operation4();void operation5();
}class B implements Interface1 {public void operation1() {System.out.println("B 实现了 operation1");}public void operation2() {System.out.println("B 实现了 operation2");}public void operation3() {System.out.println("B 实现了 operation3");}public void operation4() {System.out.println("B 实现了 operation4");}public void operation5() {System.out.println("B 实现了 operation5");}
}class D implements Interface1 {public void operation1() {System.out.println("D 实现了 operation1");}public void operation2() {System.out.println("D 实现了 operation2");}public void operation3() {System.out.println("D 实现了 operation3");}public void operation4() {System.out.println("D 实现了 operation4");}public void operation5() {System.out.println("D 实现了 operation5");}
}class A { //A 类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法public void depend1(Interface1 i) {i.operation1();}public void depend2(Interface1 i) {i.operation2();}public void depend3(Interface1 i) {i.operation3();}
}class C { //C 类通过接口Interface1 依赖(使用) D类,但是只会用到1,4,5方法public void depend1(Interface1 i) {i.operation1();}public void depend4(Interface1 i) {i.operation4();}public void depend5(Interface1 i) {i.operation5();}
}

package com.atguigu.principle.segregation.improve;public class Segregation1 {public static void main(String[] args) {// TODO Auto-generated method stub// 使用一把A a = new A();a.depend1(new B()); // A类通过接口去依赖B类a.depend2(new B());a.depend3(new B());C c = new C();c.depend1(new D()); // C类通过接口去依赖(使用)D类c.depend4(new D());c.depend5(new D());}}// 接口1
interface Interface1 {void operation1();}// 接口2
interface Interface2 {void operation2();void operation3();
}// 接口3
interface Interface3 {void operation4();void operation5();
}class B implements Interface1, Interface2 {public void operation1() {System.out.println("B 实现了 operation1");}public void operation2() {System.out.println("B 实现了 operation2");}public void operation3() {System.out.println("B 实现了 operation3");}}class D implements Interface1, Interface3 {public void operation1() {System.out.println("D 实现了 operation1");}public void operation4() {System.out.println("D 实现了 operation4");}public void operation5() {System.out.println("D 实现了 operation5");}
}class A { // A 类通过接口Interface1,Interface2 依赖(使用) B类,但是只会用到1,2,3方法public void depend1(Interface1 i) {i.operation1();}public void depend2(Interface2 i) {i.operation2();}public void depend3(Interface2 i) {i.operation3();}
}class C { // C 类通过接口Interface1,Interface3 依赖(使用) D类,但是只会用到1,4,5方法public void depend1(Interface1 i) {i.operation1();}public void depend4(Interface3 i) {i.operation4();}public void depend5(Interface3 i) {i.operation5();}
}

2.5 ③依赖倒转原则

方案1 

package com.atguigu.principle.inversion;public class DependecyInversion {public static void main(String[] args) {Person person = new Person();person.receive(new Email());}}class Email {public String getInfo() {return "电子邮件信息: hello,world";}
}//完成Person接收消息的功能
//方式1分析
//1. 简单,比较容易想到
//2. 如果我们获取的对象是 微信,短信等等,则新增类,同时Perons也要增加相应的接收方法
//3. 解决思路:引入一个抽象的接口IReceiver, 表示接收者, 这样Person类与接口IReceiver发生依赖
//   因为Email, WeiXin 等等属于接收的范围,他们各自实现IReceiver 接口就ok, 这样我们就符号依赖倒转原则
class Person {public void receive(Email email ) {System.out.println(email.getInfo());}
}

方案2(改进)

package com.atguigu.principle.inversion.improve;public class DependecyInversion {public static void main(String[] args) {//客户端无需改变Person person = new Person();person.receive(new Email());person.receive(new WeiXin());}}//定义接口
interface IReceiver {public String getInfo();
}class Email implements IReceiver {public String getInfo() {return "电子邮件信息: hello,world";}
}//增加微信
class WeiXin implements IReceiver {public String getInfo() {return "微信信息: hello,ok";}
}//方式2
class Person {//这里我们是对接口的依赖public void receive(IReceiver receiver ) {System.out.println(receiver.getInfo());}
}

package com.atguigu.principle.inversion.improve;public class DependencyPass {public static void main(String[] args) {// TODO Auto-generated method stubChangHong changHong = new ChangHong();
//		OpenAndClose openAndClose = new OpenAndClose();
//		openAndClose.open(changHong);//通过构造器进行依赖传递
//		OpenAndClose openAndClose = new OpenAndClose(changHong);
//		openAndClose.open();//通过setter方法进行依赖传递OpenAndClose openAndClose = new OpenAndClose();openAndClose.setTv(changHong);openAndClose.open();}}// 方式1: 通过接口传递实现依赖
// 开关的接口
// interface IOpenAndClose {
// public void open(ITV tv); //抽象方法,接收接口
// }
//
// interface ITV { //ITV接口
// public void play();
// }
// 
// class ChangHong implements ITV {
//
//	@Override
//	public void play() {
//		// TODO Auto-generated method stub
//		System.out.println("长虹电视机,打开");
//	}
//	 
// }实现接口
// class OpenAndClose implements IOpenAndClose{
// public void open(ITV tv){
// tv.play();
// }
// }// 方式2: 通过构造方法依赖传递
// interface IOpenAndClose {
// public void open(); //抽象方法
// }
// interface ITV { //ITV接口
// public void play();
// }
// class OpenAndClose implements IOpenAndClose{
// public ITV tv; //成员
// public OpenAndClose(ITV tv){ //构造器
// this.tv = tv;
// }
// public void open(){
// this.tv.play();
// }
// }// 方式3 , 通过setter方法传递
interface IOpenAndClose {public void open(); // 抽象方法public void setTv(ITV tv);
}interface ITV { // ITV接口public void play();
}class OpenAndClose implements IOpenAndClose {private ITV tv;public void setTv(ITV tv) {this.tv = tv;}public void open() {this.tv.play();}
}class ChangHong implements ITV {@Overridepublic void play() {// TODO Auto-generated method stubSystem.out.println("长虹电视机,打开");}}

2.6 ④里氏替换原则

package com.atguigu.principle.liskov;public class Liskov {public static void main(String[] args) {// TODO Auto-generated method stubA a = new A();System.out.println("11-3=" + a.func1(11, 3));System.out.println("1-8=" + a.func1(1, 8));System.out.println("-----------------------");B b = new B();System.out.println("11-3=" + b.func1(11, 3));//这里本意是求出11-3System.out.println("1-8=" + b.func1(1, 8));// 1-8System.out.println("11+3+9=" + b.func2(11, 3));}
}// A类
class A {// 返回两个数的差public int func1(int num1, int num2) {return num1 - num2;}
}// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends A {//这里,重写了A类的方法, 可能是无意识public int func1(int a, int b) {return a + b;}public int func2(int a, int b) {return func1(a, b) + 9;}
}

改进方案 

package com.atguigu.principle.liskov.improve;public class Liskov {public static void main(String[] args) {// TODO Auto-generated method stubA a = new A();System.out.println("11-3=" + a.func1(11, 3));System.out.println("1-8=" + a.func1(1, 8));System.out.println("-----------------------");B b = new B();//因为B类不再继承A类,因此调用者,不会再func1是求减法//调用完成的功能就会很明确System.out.println("11+3=" + b.func1(11, 3));//这里本意是求出11+3System.out.println("1+8=" + b.func1(1, 8));// 1+8System.out.println("11+3+9=" + b.func2(11, 3));//使用组合仍然可以使用到A类相关方法System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3}}//创建一个更加基础的基类
class Base {//把更加基础的方法和成员写到Base类
}// A类
class A extends Base {// 返回两个数的差public int func1(int num1, int num2) {return num1 - num2;}
}// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends Base {//如果B需要使用A类的方法,使用组合关系private A a = new A();//这里,重写了A类的方法, 可能是无意识public int func1(int a, int b) {return a + b;}public int func2(int a, int b) {return func1(a, b) + 9;}//我们仍然想使用A的方法public int func3(int a, int b) {return this.a.func1(a, b);}
}

2.7 ⑤开闭原则

package com.atguigu.principle.ocp;public class Ocp {public static void main(String[] args) {//使用看看存在的问题GraphicEditor graphicEditor = new GraphicEditor();graphicEditor.drawShape(new Rectangle());graphicEditor.drawShape(new Circle());graphicEditor.drawShape(new Triangle());}}//这是一个用于绘图的类 [使用方]
class GraphicEditor {//接收Shape对象,然后根据type,来绘制不同的图形public void drawShape(Shape s) {if (s.m_type == 1)drawRectangle(s);else if (s.m_type == 2)drawCircle(s);else if (s.m_type == 3)drawTriangle(s);}//绘制矩形public void drawRectangle(Shape r) {System.out.println(" 绘制矩形 ");}//绘制圆形public void drawCircle(Shape r) {System.out.println(" 绘制圆形 ");}//绘制三角形public void drawTriangle(Shape r) {System.out.println(" 绘制三角形 ");}
}//Shape类,基类
class Shape {int m_type;
}class Rectangle extends Shape {Rectangle() {super.m_type = 1;}
}class Circle extends Shape {Circle() {super.m_type = 2;}
}//新增画三角形
class Triangle extends Shape {Triangle() {super.m_type = 3;}
}

方式2(改进) 

package com.atguigu.principle.ocp.improve;public class Ocp {public static void main(String[] args) {//使用看看存在的问题GraphicEditor graphicEditor = new GraphicEditor();graphicEditor.drawShape(new Rectangle());graphicEditor.drawShape(new Circle());graphicEditor.drawShape(new Triangle());graphicEditor.drawShape(new OtherGraphic());}}//这是一个用于绘图的类 [使用方]
class GraphicEditor {//接收Shape对象,调用draw方法public void drawShape(Shape s) {s.draw();}}//Shape类,基类
abstract class Shape {int m_type;public abstract void draw();//抽象方法
}class Rectangle extends Shape {Rectangle() {super.m_type = 1;}@Overridepublic void draw() {// TODO Auto-generated method stubSystem.out.println(" 绘制矩形 ");}
}class Circle extends Shape {Circle() {super.m_type = 2;}@Overridepublic void draw() {// TODO Auto-generated method stubSystem.out.println(" 绘制圆形 ");}
}//新增画三角形
class Triangle extends Shape {Triangle() {super.m_type = 3;}@Overridepublic void draw() {// TODO Auto-generated method stubSystem.out.println(" 绘制三角形 ");}
}//新增一个图形
class OtherGraphic extends Shape {OtherGraphic() {super.m_type = 4;}@Overridepublic void draw() {// TODO Auto-generated method stubSystem.out.println(" 绘制其它图形 ");}
}

2.8 ⑥迪米特法则

package com.atguigu.principle.demeter;import java.util.ArrayList;
import java.util.List;//客户端
public class Demeter1 {public static void main(String[] args) {//创建了一个 SchoolManager 对象SchoolManager schoolManager = new SchoolManager();//输出学院的员工id 和  学校总部的员工信息schoolManager.printAllEmployee(new CollegeManager());}}//学校总部员工类
class Employee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}//学院的员工类
class CollegeEmployee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}//管理学院员工的管理类
class CollegeManager {//返回学院的所有员工public List<CollegeEmployee> getAllEmployee() {List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 listCollegeEmployee emp = new CollegeEmployee();emp.setId("学院员工id= " + i);list.add(emp);}return list;}
}//学校管理类//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则 
class SchoolManager {//返回学校总部的员工public List<Employee> getAllEmployee() {List<Employee> list = new ArrayList<Employee>();for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 listEmployee emp = new Employee();emp.setId("学校总部员工id= " + i);list.add(emp);}return list;}//该方法完成输出学校总部和学院员工信息(id)void printAllEmployee(CollegeManager sub) {//分析问题//1. 这里的 CollegeEmployee 不是  SchoolManager的直接朋友//2. CollegeEmployee 是以局部变量方式出现在 SchoolManager//3. 违反了 迪米特法则 //获取到学院员工List<CollegeEmployee> list1 = sub.getAllEmployee();System.out.println("------------学院员工------------");for (CollegeEmployee e : list1) {System.out.println(e.getId());}//获取到学校总部员工List<Employee> list2 = this.getAllEmployee();System.out.println("------------学校总部员工------------");for (Employee e : list2) {System.out.println(e.getId());}}
}

改进代码

package com.atguigu.principle.demeter.improve;import java.util.ArrayList;
import java.util.List;//客户端
public class Demeter1 {public static void main(String[] args) {System.out.println("~~~使用迪米特法则的改进~~~");//创建了一个 SchoolManager 对象SchoolManager schoolManager = new SchoolManager();//输出学院的员工id 和  学校总部的员工信息schoolManager.printAllEmployee(new CollegeManager());}}//学校总部员工类
class Employee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}//学院的员工类
class CollegeEmployee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}//管理学院员工的管理类
class CollegeManager {//返回学院的所有员工public List<CollegeEmployee> getAllEmployee() {List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 listCollegeEmployee emp = new CollegeEmployee();emp.setId("学院员工id= " + i);list.add(emp);}return list;}//输出学院员工的信息public void printEmployee() {//获取到学院员工List<CollegeEmployee> list1 = getAllEmployee();System.out.println("------------学院员工------------");for (CollegeEmployee e : list1) {System.out.println(e.getId());}}
}//学校管理类//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则 
class SchoolManager {//返回学校总部的员工public List<Employee> getAllEmployee() {List<Employee> list = new ArrayList<Employee>();for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 listEmployee emp = new Employee();emp.setId("学校总部员工id= " + i);list.add(emp);}return list;}//该方法完成输出学校总部和学院员工信息(id)void printAllEmployee(CollegeManager sub) {//分析问题//1. 将输出学院的员工方法,封装到CollegeManagersub.printEmployee();//获取到学校总部员工List<Employee> list2 = this.getAllEmployee();System.out.println("------------学校总部员工------------");for (Employee e : list2) {System.out.println(e.getId());}}
}

2.9 ⑦合成复用原则(Composite Reuse Principle)

2.10 设计原则核心思想

第3章 UML类图

3.1 UML基本介绍

3.2 UML图

3.3 UML类图

3.4 类图—依赖关系(Dependence)

3.5 类图-泛化关系(generalization)

3.6 类图-实现关系(Implementation)

3.7 类图-关联关系(Association)

3.8 类图-聚合关系(Aggregation)

3.9 类图-组合关系(Composition)

第4章 设计模式概述

4.1 掌握设计模式的层次

4.2 设计模式介绍

4.3 设计模式类型

创建型模式: 

第5章 1单例设计模式(singleton)★

5.1 单例设计模式介绍

5.2 单例设计模式八种方式

5.3 ①饿汉式(静态常量)

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

5.4 ②饿汉式(静态代码块)

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

5.5 ③懒汉式(线程不安全)

package com.atguigu.singleton.type3;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); // trueSystem.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;}
}

5.6 ④懒汉式(线程安全,同步方法)

package com.atguigu.singleton.type4;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); // trueSystem.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;}
}

5.7 ⑤懒汉式(线程安全,同步代码块)

5.8 ⑥双重检查(DoubleCheck)

package com.atguigu.singleton.type6;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); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}// 懒汉式(线程安全,同步方法)
class Singleton {private static volatile Singleton instance;private Singleton() {}//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题//同时保证了效率, 推荐使用public static synchronized Singleton getInstance() {if(instance == null) {synchronized (Singleton.class) {if(instance == null) {instance = new Singleton();}}}return instance;}
}

5.9 ⑦静态内部类

package com.atguigu.singleton.type7;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); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}// 静态内部类完成单例模式,推荐使用
class Singleton {private static volatile Singleton instance;//构造器私有化private Singleton() {}//写一个静态内部类,该类中有一个静态属性 Singletonprivate static class SingletonInstance {private static final Singleton INSTANCE = new Singleton(); }//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCEpublic static synchronized Singleton getInstance() {return SingletonInstance.INSTANCE;}
}

5.10 ⑧枚举

package com.atguigu.singleton.type8;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~");}
}

5.11 单例模式在JDK应用的源码分析

5.12 单例模式注意事项和细节说明

第6章 2工厂模式(factory)★

6.1 ①简单工厂模式

prepare:准备原材料        bake:烘烤        cut:切割        box:打包

传统方式 

package com.atguigu.factory.simplefactory.pizzastore.pizza;//将Pizza 类做成抽象
public abstract class Pizza {protected String name; //名字//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法public abstract void prepare();public void bake() {System.out.println(name + " baking;");}public void cut() {System.out.println(name + " cutting;");}//打包public void box() {System.out.println(name + " boxing;");}public void setName(String name) {this.name = name;}
}
package com.atguigu.factory.simplefactory.pizzastore.pizza;public class CheesePizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubSystem.out.println(" 给制作奶酪披萨 准备原材料 ");}}
package com.atguigu.factory.simplefactory.pizzastore.pizza;public class GreekPizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubSystem.out.println(" 给希腊披萨 准备原材料 ");}}
package com.atguigu.factory.simplefactory.pizzastore.pizza;public class PepperPizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubSystem.out.println(" 给胡椒披萨准备原材料 ");}}

 订购披萨

package com.atguigu.factory.simplefactory.pizzastore.order;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;import com.atguigu.factory.simplefactory.pizzastore.pizza.Pizza;public class OrderPizza {// 构造器public OrderPizza() {Pizza pizza = null;String orderType; // 订购披萨的类型do {orderType = getType();if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希腊披萨 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披萨 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披萨");} else {break;}//输出pizza 制作过程pizza.prepare();pizza.bake();pizza.cut();pizza.box();} while (true);}// 写一个方法,可以获取客户希望订购的披萨种类private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 种类:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}}

披萨店(客户端) 

package com.atguigu.factory.simplefactory.pizzastore.order;//相当于一个客户端,发出订购
public class PizzaStore {public static void main(String[] args) {new OrderPizza();}
}

package com.atguigu.factory.simplefactory.pizzastore.order;import com.atguigu.factory.simplefactory.pizzastore.pizza.CheesePizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.GreekPizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.PepperPizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.Pizza;//简单工厂类
public class SimpleFactory {//根据orderType 返回对应的Pizza 对象public Pizza createPizza(String orderType) {Pizza pizza = null;System.out.println("使用简单工厂模式");if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希腊披萨 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披萨 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披萨");}return pizza;}}
package com.atguigu.factory.simplefactory.pizzastore.order;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;import com.atguigu.factory.simplefactory.pizzastore.pizza.Pizza;public class OrderPizza {//定义一个简单工厂对象SimpleFactory simpleFactory;Pizza pizza = null;//构造器public OrderPizza(SimpleFactory simpleFactory) {setFactory(simpleFactory);}public void setFactory(SimpleFactory simpleFactory) {String orderType = ""; //用户输入的this.simpleFactory = simpleFactory; //设置简单工厂对象do {orderType = getType(); pizza = this.simpleFactory.createPizza(orderType);//输出pizzaif(pizza != null) { //订购成功pizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println(" 订购披萨失败 ");break;}}while(true);}// 写一个方法,可以获取客户希望订购的披萨种类private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 种类:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}}

披萨店(客户端) 

package com.atguigu.factory.simplefactory.pizzastore.order;//相当于一个客户端,发出订购
public class PizzaStore {public static void main(String[] args) {// TODO Auto-generated method stub//new OrderPizza();//使用简单工厂模式new OrderPizza(new SimpleFactory());System.out.println("~~退出程序~~");}
}

简单工厂模式额外补充说明(静态工厂模式),方法变为静态,调用更加方便

package com.atguigu.factory.simplefactory.pizzastore.order;import com.atguigu.factory.simplefactory.pizzastore.pizza.CheesePizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.GreekPizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.PepperPizza;
import com.atguigu.factory.simplefactory.pizzastore.pizza.Pizza;//简单工厂类
public class SimpleFactory {//根据orderType 返回对应的Pizza 对象public Pizza createPizza(String orderType) {Pizza pizza = null;System.out.println("使用简单工厂模式");if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希腊披萨 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披萨 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披萨");}return pizza;}//额外补充:简单工厂模式 也叫 静态工厂模式 	public static Pizza createPizza2(String orderType) {Pizza pizza = null;System.out.println("使用简单工厂模式2");if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希腊披萨 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披萨 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披萨");}return pizza;}}
package com.atguigu.factory.simplefactory.pizzastore.order;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;import com.atguigu.factory.simplefactory.pizzastore.pizza.Pizza;public class OrderPizza2 {Pizza pizza = null;String orderType = "";// 构造器public OrderPizza2() {do {orderType = getType();pizza = SimpleFactory.createPizza2(orderType);// 输出pizzaif (pizza != null) { // 订购成功pizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println(" 订购披萨失败 ");break;}} while (true);}// 写一个方法,可以获取客户希望订购的披萨种类private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 种类:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}

 披萨店(客户端),使用静态方法,不用再传入工厂对象参数

package com.atguigu.factory.simplefactory.pizzastore.order;//相当于一个客户端,发出订购
public class PizzaStore {public static void main(String[] args) {// TODO Auto-generated method stub//new OrderPizza();//使用简单工厂模式//new OrderPizza(new SimpleFactory());//System.out.println("~~退出程序~~");//使用静态方法,不用再传入工厂对象参数new OrderPizza2();}}

6.2 ②工厂方法模式

pizza

package com.atguigu.factory.factorymethod.pizzastore.pizza;//将Pizza 类做成抽象
public abstract class Pizza {protected String name; //名字//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法public abstract void prepare();public void bake() {System.out.println(name + " baking;");}public void cut() {System.out.println(name + " cutting;");}//打包public void box() {System.out.println(name + " boxing;");}public void setName(String name) {this.name = name;}
}
package com.atguigu.factory.factorymethod.pizzastore.pizza;public class BJCheesePizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("北京的奶酪pizza");System.out.println(" 北京的奶酪pizza 准备原材料");}
}
package com.atguigu.factory.factorymethod.pizzastore.pizza;public class BJPepperPizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("北京的胡椒pizza");System.out.println(" 北京的胡椒pizza 准备原材料");}
}
package com.atguigu.factory.factorymethod.pizzastore.pizza;public class LDCheesePizza extends Pizza{@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("伦敦的奶酪pizza");System.out.println(" 伦敦的奶酪pizza 准备原材料");}
}
package com.atguigu.factory.factorymethod.pizzastore.pizza;public class LDPepperPizza extends Pizza{@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("伦敦的胡椒pizza");System.out.println(" 伦敦的胡椒pizza 准备原材料");}
}

order

package com.atguigu.factory.factorymethod.pizzastore.order;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.atguigu.factory.factorymethod.pizzastore.pizza.Pizza;public abstract class OrderPizza {//定义一个抽象方法,createPizza , 让各个工厂子类自己实现abstract Pizza createPizza(String orderType);// 构造器public OrderPizza() {Pizza pizza = null;String orderType; // 订购披萨的类型do {orderType = getType();pizza = createPizza(orderType); //抽象方法,由工厂子类完成//输出pizza 制作过程pizza.prepare();pizza.bake();pizza.cut();pizza.box();} while (true);}// 写一个方法,可以获取客户希望订购的披萨种类private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 种类:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}
package com.atguigu.factory.factorymethod.pizzastore.order;import com.atguigu.factory.factorymethod.pizzastore.pizza.BJCheesePizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.BJPepperPizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.Pizza;public class BJOrderPizza extends OrderPizza {@OverridePizza createPizza(String orderType) {Pizza pizza = null;if(orderType.equals("cheese")) {pizza = new BJCheesePizza();} else if (orderType.equals("pepper")) {pizza = new BJPepperPizza();}// TODO Auto-generated method stubreturn pizza;}
}
package com.atguigu.factory.factorymethod.pizzastore.order;import com.atguigu.factory.factorymethod.pizzastore.pizza.BJCheesePizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.BJPepperPizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.LDCheesePizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.LDPepperPizza;
import com.atguigu.factory.factorymethod.pizzastore.pizza.Pizza;public class LDOrderPizza extends OrderPizza {@OverridePizza createPizza(String orderType) {Pizza pizza = null;if(orderType.equals("cheese")) {pizza = new LDCheesePizza();} else if (orderType.equals("pepper")) {pizza = new LDPepperPizza();}// TODO Auto-generated method stubreturn pizza;}
}

披萨店(客户端)

package com.atguigu.factory.factorymethod.pizzastore.order;public class PizzaStore {public static void main(String[] args) {String loc = "bj";if (loc.equals("bj")) {//创建北京口味的各种Pizzanew BJOrderPizza();} else {//创建伦敦口味的各种Pizzanew LDOrderPizza();}// TODO Auto-generated method stub}}

6.3 ③抽象工厂模式

pizza(列举BJCheesePizza、LDCheesePizza)

package com.atguigu.factory.absfactory.pizzastore.pizza;//将Pizza 类做成抽象
public abstract class Pizza {protected String name; //名字//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法public abstract void prepare();public void bake() {System.out.println(name + " baking;");}public void cut() {System.out.println(name + " cutting;");}//打包public void box() {System.out.println(name + " boxing;");}public void setName(String name) {this.name = name;}
}
package com.atguigu.factory.absfactory.pizzastore.pizza;public class BJCheesePizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("北京的奶酪pizza");System.out.println(" 北京的奶酪pizza 准备原材料");}
}
package com.atguigu.factory.absfactory.pizzastore.pizza;public class LDCheesePizza extends Pizza{@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("伦敦的奶酪pizza");System.out.println(" 伦敦的奶酪pizza 准备原材料");}
}

order

package com.atguigu.factory.absfactory.pizzastore.order;import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {//让下面的工厂子类来 具体实现public Pizza createPizza(String orderType);
}
package com.atguigu.factory.absfactory.pizzastore.order;import com.atguigu.factory.absfactory.pizzastore.pizza.BJCheesePizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.BJPepperPizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;//这是工厂子类
public class BJFactory implements AbsFactory {@Overridepublic Pizza createPizza(String orderType) {System.out.println("~使用的是抽象工厂模式~");// TODO Auto-generated method stubPizza pizza = null;if(orderType.equals("cheese")) {pizza = new BJCheesePizza();} else if (orderType.equals("pepper")){pizza = new BJPepperPizza();}return pizza;}
}
package com.atguigu.factory.absfactory.pizzastore.order;import com.atguigu.factory.absfactory.pizzastore.pizza.LDCheesePizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.LDPepperPizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;//这是工厂子类
public class LDFactory implements AbsFactory {@Overridepublic Pizza createPizza(String orderType) {System.out.println("~使用的是抽象工厂模式~");Pizza pizza = null;if (orderType.equals("cheese")) {pizza = new LDCheesePizza();} else if (orderType.equals("pepper")) {pizza = new LDPepperPizza();}return pizza;}
}

OrderPizza

package com.atguigu.factory.absfactory.pizzastore.order;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;public class OrderPizza {AbsFactory factory;// 构造器public OrderPizza(AbsFactory factory) {setFactory(factory);}private void setFactory(AbsFactory factory) {Pizza pizza = null;String orderType = ""; // 用户输入this.factory = factory;do {orderType = getType();// factory 可能是北京的工厂子类,也可能是伦敦的工厂子类pizza = factory.createPizza(orderType);if (pizza != null) { // 订购okpizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println("订购失败");break;}} while (true);}// 写一个方法,可以获取客户希望订购的披萨种类private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 种类:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}

披萨店(客户端)

package com.atguigu.factory.absfactory.pizzastore.order;public class PizzaStore {public static void main(String[] args) {// TODO Auto-generated method stub//new OrderPizza(new BJFactory());new OrderPizza(new LDFactory());}
}

6.4 工厂模式在JDK-Calendar应用的源码分析

private static Calendar createCalendar(TimeZone zone,Locale aLocale)//根据 zone,aLocale创建对应实例
{CalendarProvider provider =LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();if (provider != null) {try {return provider.getInstance(zone, aLocale);} catch (IllegalArgumentException iae) {// fall back to the default instantiation}}Calendar cal = null;if (aLocale.hasExtensions()) {String caltype = aLocale.getUnicodeLocaleType("ca");if (caltype != null) {switch (caltype) {case "buddhist":cal = new BuddhistCalendar(zone, aLocale);break;case "japanese":cal = new JapaneseImperialCalendar(zone, aLocale);break;case "gregory":cal = new GregorianCalendar(zone, aLocale);break;}}}if (cal == null) {// If no known calendar type is explicitly specified,// perform the traditional way to create a Calendar:// create a BuddhistCalendar for th_TH locale,// a JapaneseImperialCalendar for ja_JP_JP locale, or// a GregorianCalendar for any other locales.// NOTE: The language, country and variant strings are interned.if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {cal = new BuddhistCalendar(zone, aLocale);} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"&& aLocale.getCountry() == "JP") {cal = new JapaneseImperialCalendar(zone, aLocale);} else {cal = new GregorianCalendar(zone, aLocale);}}return cal;
}

6.5 工厂模式小结

第7章 3原型模式(prototype)

7.1 克隆羊问题

7.2 传统方式解决克隆羊问题

package com.atguigu.prototype;public class Sheep {private String name;private int age;private String color;public Sheep(String name, int age, String color) {super();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;}@Overridepublic String toString() {return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";}}
package com.atguigu.prototype;public class Client {public static void main(String[] args) {// TODO Auto-generated method stub//传统的方法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);//...}}

7.3 传统的方式的优缺点

7.4 原型模式-基本介绍

7.5 原型模式原理结构图-uml类图

7.6 原型模式解决克隆羊问题的应用实例

package com.atguigu.prototype.improve;public class Sheep implements Cloneable {private String name;private int age;private String color;private String address = "蒙古羊";public Sheep(String name, int age, String color) {super();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;}@Overridepublic String toString() {return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";}//克隆该实例,使用默认的clone方法来完成@Overrideprotected Object clone()  {Sheep sheep = null;try {sheep = (Sheep)super.clone();} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}// TODO Auto-generated method stubreturn sheep;}}
package com.atguigu.prototype.improve;public class Client {public static void main(String[] args) {System.out.println("原型模式完成对象的创建");// TODO Auto-generated method stubSheep sheep = new Sheep("tom", 1, "白色");Sheep sheep2 = (Sheep)sheep.clone(); //克隆Sheep sheep3 = (Sheep)sheep.clone(); //克隆Sheep sheep4 = (Sheep)sheep.clone(); //克隆Sheep sheep5 = (Sheep)sheep.clone(); //克隆System.out.println("sheep2 =" + sheep2 );System.out.println("sheep3 =" + sheep3 );System.out.println("sheep4 =" + sheep4 );System.out.println("sheep5 =" + sheep5 );}
}

7.7 原型模式在Spring框架中源码分析★

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- 这里我们的 scope="prototype" 即 原型模式来创建 -->
<bean id="id01" class="com.atguigu.spring.bean.Monster" scope="prototype"/></beans>
package com.atguigu.spring.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ProtoType {public static void main(String[] args) {// TODO Auto-generated method stubApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");// 获取monster[通过id获取monster]Object bean = applicationContext.getBean("id01");System.out.println("bean" + bean); // 输出 "牛魔王" .....Object bean2 = applicationContext.getBean("id01");System.out.println("bean2" + bean2); //输出 "牛魔王" .....System.out.println(bean == bean2); // false// ConfigurableApplicationContext}}

源码追踪

。。。。。。

7.8 深入讨论-浅拷贝和深拷贝

Object.Clone()方法默认情况下是浅拷贝

package com.atguigu.prototype.improve;public class Sheep implements Cloneable {private String name;private int age;private String color;private String address = "蒙古羊";public Sheep friend; //是对象, 克隆是会如何处理?默认是浅拷贝public Sheep(String name, int age, String color) {super();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;}@Overridepublic String toString() {return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";}//克隆该实例,使用默认的clone方法来完成@Overrideprotected Object clone()  {Sheep sheep = null;try {sheep = (Sheep)super.clone();} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}// TODO Auto-generated method stubreturn sheep;}}
package com.atguigu.prototype.improve;public class Client {public static void main(String[] args) {System.out.println("原型模式完成对象的创建");// TODO Auto-generated method stubSheep sheep = new Sheep("tom", 1, "白色");sheep.friend = new Sheep("jack", 2, "黑色");Sheep sheep2 = (Sheep)sheep.clone(); //克隆Sheep sheep3 = (Sheep)sheep.clone(); //克隆Sheep sheep4 = (Sheep)sheep.clone(); //克隆Sheep sheep5 = (Sheep)sheep.clone(); //克隆System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());}
}

Object.clone()方法默认为浅拷贝 

7.9 深拷贝应用实例

package com.atguigu.prototype.deepclone;import java.io.Serializable;public class DeepCloneableTarget implements Serializable, Cloneable {/*** */private static final long serialVersionUID = 1L;private String cloneName;private String cloneClass;//构造器public DeepCloneableTarget(String cloneName, String cloneClass) {this.cloneName = cloneName;this.cloneClass = cloneClass;}//因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
package com.atguigu.prototype.deepclone;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;public class DeepProtoType implements Serializable, Cloneable{public String name; //String 属性public DeepCloneableTarget deepCloneableTarget;// 引用类型public DeepProtoType() {super();}//深拷贝 - 方式 1 使用clone 方法@Overrideprotected Object clone() throws CloneNotSupportedException {Object deep = null;//这里完成对基本数据类型(属性)和String的克隆deep = super.clone(); //对引用类型的属性,进行单独处理DeepProtoType deepProtoType = (DeepProtoType)deep;deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();// TODO Auto-generated method stubreturn deepProtoType;}//深拷贝 - 方式2 通过对象的序列化实现 (推荐)	public Object deepClone() {//创建流对象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);DeepProtoType copyObj = (DeepProtoType)ois.readObject();return copyObj;} catch (Exception e) {// TODO: handle exceptione.printStackTrace();return null;} finally {//关闭流try {bos.close();oos.close();bis.close();ois.close();} catch (Exception e2) {// TODO: handle exceptionSystem.out.println(e2.getMessage());}}	}	
}

客户端

package com.atguigu.prototype.deepclone;public class Client {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubDeepProtoType p = new DeepProtoType();p.name = "宋江";p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");//方式1 完成深拷贝//		DeepProtoType p2 = (DeepProtoType) p.clone();
//		
//		System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
//		System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());//方式2 完成深拷贝DeepProtoType p2 = (DeepProtoType) p.deepClone();System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());}
}

方式1-使用重写clone()方法实现深拷贝:对引用类型的属性,进行单独处理 

方式2-使用序列化来实现深拷贝:当前这个对象以对象流的方式输出,再以对象流的方式读入(读入的时候就拷贝了一份)

方式1则需要对引用类型的属性,进行单独处理,每有一个则处理一次,即:调用一次clone();方式2的优势在于拷贝的时候传入this,对整个对象进行拷贝处理(将this以对象流的方式先输出后输入

7.10 原型模式的注意事项和细节

第8章 4建造者模式(builder)

8.1 盖房项目需求

8.2 传统方式解决盖房需求

package com.atguigu.builder;public abstract class AbstractHouse {//打地基public abstract void buildBasic();//砌墙public abstract void buildWalls();//封顶public abstract void roofed();public void build() {buildBasic();buildWalls();roofed();}}
package com.atguigu.builder;public class CommonHouse extends AbstractHouse {@Overridepublic void buildBasic() {// TODO Auto-generated method stubSystem.out.println(" 普通房子打地基 ");}@Overridepublic void buildWalls() {// TODO Auto-generated method stubSystem.out.println(" 普通房子砌墙 ");}@Overridepublic void roofed() {// TODO Auto-generated method stubSystem.out.println(" 普通房子封顶 ");}}

客户端

package com.atguigu.builder;public class Client {public static void main(String[] args) {// TODO Auto-generated method stubCommonHouse commonHouse = new CommonHouse();commonHouse.build();}}

8.3 传统方式的问题分析

8.4 建造者模式基本介绍

8.5 建造者模式的四个角色

8.6 建造者模式原理类图

8.7 建造者模式解决盖房需求应用实例

package com.atguigu.builder.improve;//产品->Product
@Data
public class House {private String baise;private String wall;private String roofed;
}
package com.atguigu.builder.improve;// 抽象的建造者
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;}}
package com.atguigu.builder.improve;public class CommonHouse extends HouseBuilder {@Overridepublic void buildBasic() {System.out.println(" 普通房子打地基5米 ");}@Overridepublic void buildWalls() {System.out.println(" 普通房子砌墙10cm ");}@Overridepublic void roofed() {System.out.println(" 普通房子屋顶 ");}}
package com.atguigu.builder.improve;public class HighBuilding extends HouseBuilder {@Overridepublic void buildBasic() {System.out.println(" 高楼的打地基100米 ");}@Overridepublic void buildWalls() {System.out.println(" 高楼的砌墙20cm ");}@Overridepublic void roofed() {System.out.println(" 高楼的透明屋顶 ");}}
package com.atguigu.builder.improve;//指挥者,这里去指定制作流程,返回产品
public class HouseDirector {HouseBuilder houseBuilder = null;//构造器传入 houseBuilderpublic HouseDirector(HouseBuilder houseBuilder) {this.houseBuilder = houseBuilder;}//通过setter 传入 houseBuilderpublic void setHouseBuilder(HouseBuilder houseBuilder) {this.houseBuilder = houseBuilder;}//如何处理建造房子的流程,交给指挥者public House constructHouse() {houseBuilder.buildBasic();houseBuilder.buildWalls();houseBuilder.roofed();return houseBuilder.buildHouse();}}
package com.atguigu.builder.improve;public class Client {public static void main(String[] args) {//盖普通房子CommonHouse commonHouse = new CommonHouse();//准备创建房子的指挥者HouseDirector houseDirector = new HouseDirector(commonHouse);//完成盖房子,返回产品(普通房子)House house = houseDirector.constructHouse();//System.out.println("输出流程");System.out.println("--------------------------");//盖高楼HighBuilding highBuilding = new HighBuilding();//重置建造者houseDirector.setHouseBuilder(highBuilding);//完成盖房子,返回产品(高楼)houseDirector.constructHouse();}
}

8.8 建造者模式在JDK的应用和源码分析★

8.9 建造者模式的注意事项和细节

结构型模式:

第9章 5适配器设计模式(Adapter)

9.1 现实生活中的适配器例子

9.2 基本介绍

9.3 工作原理

9.4 类适配器模式

package com.atguigu.adapter.classadapter;//被适配的类
public class Voltage220V {//输出220V的电压public int output220V() {int src = 220;System.out.println("电压=" + src + "伏");return src;}
}
package com.atguigu.adapter.classadapter;//适配接口
public interface IVoltage5V {public int output5V();
}
package com.atguigu.adapter.classadapter;//适配器类
public class VoltageAdapter extends Voltage220V implements IVoltage5V {@Overridepublic int output5V() {//获取到220V电压int srcV = output220V();int dstV = srcV / 44 ; //转成 5vreturn dstV;}}
package com.atguigu.adapter.classadapter;public class Phone {//充电public void charging(IVoltage5V iVoltage5V) {if(iVoltage5V.output5V() == 5) {System.out.println("电压为5V, 可以充电~~");} else if (iVoltage5V.output5V() > 5) {System.out.println("电压大于5V, 不能充电~~");}}
}
package com.atguigu.adapter.classadapter;public class Client {public static void main(String[] args) {System.out.println(" === 类适配器模式 ====");Phone phone = new Phone();phone.charging(new VoltageAdapter());}}

9.5 对象适配器模式

package com.atguigu.adapter.objectadapter;//被适配的类
public class Voltage220V {//输出220V的电压,不变public int output220V() {int src = 220;System.out.println("电压=" + src + "伏");return src;}
}
package com.atguigu.adapter.objectadapter;//适配接口
public interface IVoltage5V {public int output5V();
}
package com.atguigu.adapter.objectadapter;//适配器类
public class VoltageAdapter  implements IVoltage5V {private Voltage220V voltage220V; // 关联关系-聚合//通过构造器,传入一个 Voltage220V 实例public VoltageAdapter(Voltage220V voltage220v) {this.voltage220V = voltage220v;}@Overridepublic int output5V() {int dst = 0;if(null != voltage220V) {int src = voltage220V.output220V();//获取220V 电压System.out.println("使用对象适配器,进行适配~~");dst = src / 44;System.out.println("适配完成,输出的电压为=" + dst);}return dst;}
}
package com.atguigu.adapter.objectadapter;public class Phone {//充电public void charging(IVoltage5V iVoltage5V) {if(iVoltage5V.output5V() == 5) {System.out.println("电压为5V, 可以充电~~");} else if (iVoltage5V.output5V() > 5) {System.out.println("电压大于5V, 不能充电~~");}}
}
package com.atguigu.adapter.objectadapter;public class Client {public static void main(String[] args) {System.out.println(" === 对象适配器模式 ====");Phone phone = new Phone();phone.charging(new VoltageAdapter(new Voltage220V()));}}

9.6 接口适配器模式

2)该抽象类的子类是以匿名内部类的方式实现的 

package com.atguigu.adapter.interfaceadapter;public interface Interface4 {public void m1();public void m2();public void m3();public void m4();
}
package com.atguigu.adapter.interfaceadapter;//在AbsAdapter 我们将 Interface4 的方法进行默认实现
public abstract class AbsAdapter implements Interface4 {//默认实现public void m1() {}public void m2() {}public void m3() {}public void m4() {}
}

客户端 

package com.atguigu.adapter.interfaceadapter;public class Client {public static void main(String[] args) {AbsAdapter absAdapter = new AbsAdapter() {//只需要去覆盖我们 需要使用 接口方法@Overridepublic void m1() {System.out.println("使用了m1的方法");}};absAdapter.m1();}
}

9.7 适配器模式在SpringMVC框架应用的源码剖析★

DispatchServlet.doDispatch() 

DispatchServlet.getHandlerAdapter()  【HandlerAdapter】

Controller

package com.atguigu.spring.springmvc;//多种Controller实现  
public interface Controller {}class HttpController implements Controller {public void doHttpHandler() {System.out.println("http...");}
}class SimpleController implements Controller {public void doSimplerHandler() {System.out.println("simple...");}
}class AnnotationController implements Controller {public void doAnnotationHandler() {System.out.println("annotation...");}
}

HandlerAdapter 

package com.atguigu.spring.springmvc;///定义一个Adapter接口 
public interface HandlerAdapter {public boolean supports(Object handler);public void handle(Object handler);
}// 多种适配器类class SimpleHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((SimpleController) handler).doSimplerHandler();}public boolean supports(Object handler) {return (handler instanceof SimpleController);}}class HttpHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((HttpController) handler).doHttpHandler();}public boolean supports(Object handler) {return (handler instanceof HttpController);}}class AnnotationHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((AnnotationController) handler).doAnnotationHandler();}public boolean supports(Object handler) {return (handler instanceof AnnotationController);}}

DispatchServlet

package com.atguigu.spring.springmvc;import java.util.ArrayList;
import java.util.List;public class DispatchServlet {public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();public DispatchServlet() {handlerAdapters.add(new AnnotationHandlerAdapter());handlerAdapters.add(new HttpHandlerAdapter());handlerAdapters.add(new SimpleHandlerAdapter());}public void doDispatch() {// 此处模拟SpringMVC从request取handler的对象,// 适配器可以获取到希望的ControllerHttpController controller = new HttpController();// AnnotationController controller = new AnnotationController();//SimpleController controller = new SimpleController();// 得到对应适配器HandlerAdapter adapter = getHandler(controller);// 通过适配器执行对应的controller对应方法adapter.handle(controller);}public HandlerAdapter getHandler(Controller controller) {//遍历:根据得到的controller(handler), 返回对应适配器for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(controller)) {return adapter;}}return null;}public static void main(String[] args) {new DispatchServlet().doDispatch(); // http...}}

9.8 适配器模式的注意事项和细节

第10章 6桥接模式(Bridge)

10.1 手机操作问题

10.2 传统方案解决手机操作问题

10.3 传统方案解决手机操作问题分析

10.4 桥接模式(Bridge)-基本介绍

10.5 桥接模式(Bridge)-原理类图

10.6 桥接模式解决手机操作问题

FoldedPhone类调用open()方法,实际调用父类Phone.open()方法,父类Phone.open()方法实际调用具体的Vivo.open()方法。

这里Phone就像一个桥一样,将整个通路连接,从抽象层连接到具体实现。 (P68,14')

package com.atguigu.bridge;//接口
public interface Brand {void open();void close();void call();
}
package com.atguigu.bridge;public class XiaoMi implements Brand {@Overridepublic void open() {System.out.println(" 小米手机开机 ");}@Overridepublic void close() {System.out.println(" 小米手机关机 ");}@Overridepublic void call() {System.out.println(" 小米手机打电话 ");}}
package com.atguigu.bridge;public class Vivo implements Brand {@Overridepublic void open() {System.out.println(" Vivo手机开机 ");}@Overridepublic void close() {System.out.println(" Vivo手机关机 ");}@Overridepublic void call() {System.out.println(" Vivo手机打电话 ");}}
package com.atguigu.bridge;public abstract class Phone {//组合品牌private Brand brand;//构造器public Phone(Brand brand) {super();this.brand = brand;}protected void open() {this.brand.open();}protected void close() {brand.close();}protected void call() {brand.call();}}
package com.atguigu.bridge;//折叠式手机类,继承 抽象类 Phone
public class FoldedPhone extends Phone {//构造器public FoldedPhone(Brand brand) {super(brand);}public void open() {super.open();System.out.println(" 折叠样式手机 ");}public void close() {super.close();System.out.println(" 折叠样式手机 ");}public void call() {super.call();System.out.println(" 折叠样式手机 ");}
}
package com.atguigu.bridge;//直立式手机类,继承 抽象类 Phone
public class UpRightPhone extends Phone {//构造器public UpRightPhone(Brand brand) {super(brand);}public void open() {super.open();System.out.println(" 直立样式手机 ");}public void close() {super.close();System.out.println(" 直立样式手机 ");}public void call() {super.call();System.out.println(" 直立样式手机 ");}
}

客户端 

package com.atguigu.bridge;public class Client {public static void main(String[] args) {//获取折叠式手机 (样式 + 品牌 )Phone phone1 = new FoldedPhone(new XiaoMi());phone1.open();phone1.call();phone1.close();System.out.println("=======================");Phone phone2 = new FoldedPhone(new Vivo());phone2.open();phone2.call();phone2.close();System.out.println("==============");UpRightPhone phone3 = new UpRightPhone(new XiaoMi());phone3.open();phone3.call();phone3.close();System.out.println("==============");UpRightPhone phone4 = new UpRightPhone(new Vivo());phone4.open();phone4.call();phone4.close();}}

10.7 桥接模式在JDBC的源码剖析★

10.8 桥接模式的注意事项和细节

10.9 桥接模式其他应用场景

第11章 7装饰者设计模式(Decorator)★

11.1 星巴克咖啡订单项目(咖啡馆)

11.2 方案1-解决星巴克咖啡订单项目(较差)

11.3 方案1-解决星巴克咖啡订单问题分析

11.4 方案2-解决星巴克咖啡订单(好点)

11.5 方案2-解决星巴克咖啡订单问题分析

11.6 装饰者模式定义

11.7 装饰者模式原理

11.8 装饰者模式解决星巴克咖啡订单

11.9 装饰者模式下的订单:2份巧克力+1份牛奶的LongBlack

11.10 装饰者模式咖啡订单项目应用实例

抽象类Drink

package com.atguigu.decorator;public abstract class Drink {public String des; // 描述private float price = 0.0f;public String getDes() {return des;}public void setDes(String des) {this.des = des;}public float getPrice() {return price;}public void setPrice(float price) {this.price = price;}//计算费用的抽象方法//子类来实现public abstract float cost();
}

单品咖啡父类,继承Drink

package com.atguigu.decorator;public class Coffee  extends Drink {@Overridepublic float cost() {return super.getPrice();}}

具体的单品咖啡, 继承单品咖啡父类

package com.atguigu.decorator;public class Espresso extends Coffee {public Espresso() {setDes(" 意大利咖啡 ");setPrice(6.0f);}
}
package com.atguigu.decorator;public class LongBlack extends Coffee {public LongBlack() {setDes(" longblack ");setPrice(5.0f);}
}
package com.atguigu.decorator;public class ShortBlack extends Coffee{public ShortBlack() {setDes(" shortblack ");setPrice(4.0f);}
}
package com.atguigu.decorator;public class DeCaf extends Coffee {public DeCaf() {setDes(" 无因咖啡 ");setPrice(1.0f);}
}

装饰者Decorator,继承Drink

package com.atguigu.decorator;public class Decorator extends Drink {private Drink obj;public Decorator(Drink obj) { //组合this.obj = obj;}@Overridepublic float cost() {// getPrice 自己价格return super.getPrice() + obj.cost();}@Overridepublic String getDes() {// obj.getDes() 输出被装饰者的信息// des=super.des; getPrice()=super.getPrice(); 都是从父类获得return des + " " + getPrice() + " && " + obj.getDes();}}

 具体的装饰者,继承Decorator

package com.atguigu.decorator;//具体的Decorator, 这里就是调味品
public class Chocolate extends Decorator {public Chocolate(Drink obj) {super(obj);setDes(" 巧克力 ");setPrice(3.0f); // 调味品 的价格}
}
package com.atguigu.decorator;public class Milk extends Decorator {public Milk(Drink obj) {super(obj);setDes(" 牛奶 ");setPrice(2.0f); }
}
package com.atguigu.decorator;public class Soy extends Decorator{public Soy(Drink obj) {super(obj);setDes(" 豆浆  ");setPrice(1.5f);}
}

客户端 

package com.atguigu.decorator;public class CoffeeBar {public static void main(String[] args) {// 装饰者模式下的订单:2份巧克力+一份牛奶的LongBlack// 1. 点一份 LongBlackDrink order = new LongBlack();System.out.println("费用1=" + order.cost());System.out.println("描述=" + order.getDes());// 2. order 加入一份牛奶order = new Milk(order);System.out.println("order 加入一份牛奶 费用 =" + order.cost());System.out.println("order 加入一份牛奶 描述 = " + order.getDes());// 3. order 加入一份巧克力order = new Chocolate(order);System.out.println("order 加入一份牛奶 加入一份巧克力  费用 =" + order.cost());System.out.println("order 加入一份牛奶 加入一份巧克力 描述 = " + order.getDes());// 3. order 加入一份巧克力order = new Chocolate(order);System.out.println("order 加入一份牛奶 加入2份巧克力   费用 =" + order.cost());System.out.println("order 加入一份牛奶 加入2份巧克力 描述 = " + order.getDes());System.out.println("===========================");Drink order2 = new DeCaf();System.out.println("order2 无因咖啡  费用 =" + order2.cost());System.out.println("order2 无因咖啡 描述 = " + order2.getDes());order2 = new Milk(order2);System.out.println("order2 无因咖啡 加入一份牛奶  费用 =" + order2.cost());System.out.println("order2 无因咖啡 加入一份牛奶 描述 = " + order2.getDes());}
}

11.11 装饰者模式在JDK应用的源码分析★

package com.atguigu.jdk;import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStream;public class Decorator {public static void main(String[] args) throws Exception{//说明//1. InputStream 是抽象类, 类似我们前面讲的 Drink//2. FileInputStream 是  InputStream 子类,类似我们前面的 DeCaf, LongBlack//3. FilterInputStream  是  InputStream 子类:类似我们前面 的 Decorator 修饰者//4. DataInputStream 是 FilterInputStream 子类,具体的修饰者,类似前面的 Milk, Soy 等//5. FilterInputStream 类 有  protected volatile InputStream in; 即含被装饰者//6. 分析得出在jdk 的io体系中,就是使用装饰者模式DataInputStream dis = new DataInputStream(new FileInputStream("d:\\abc.txt"));System.out.println(dis.read());dis.close();}}

第12章 8组合模式(Composite)

12.1 看一个学校院系展示需求

12.2 传统方案解决学校院系展示(类图)

12.3 传统方案解决学校院系展示存在的问题分析

12.4 组合模式基本介绍

12.5 组合模式原理类图

12.6 组合模式解决学校院系展示的应用实例

package com.atguigu.composite;@Data
public abstract class OrganizationComponent {private String name; // 名字private String des; // 说明protected  void add(OrganizationComponent organizationComponent) {//默认实现throw new UnsupportedOperationException();}protected  void remove(OrganizationComponent organizationComponent) {//默认实现throw new UnsupportedOperationException();}//构造器public OrganizationComponent(String name, String des) {super();this.name = name;this.des = des;}//方法print, 做成抽象的, 子类都需要实现protected abstract void print();}
package com.atguigu.composite;import java.util.ArrayList;
import java.util.List;//University 就是 Composite , 可以管理College
public class University extends OrganizationComponent {List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();// 构造器public University(String name, String des) {super(name, des);}// 重写add@Overrideprotected void add(OrganizationComponent organizationComponent) {organizationComponents.add(organizationComponent);}// 重写remove@Overrideprotected void remove(OrganizationComponent organizationComponent) {organizationComponents.remove(organizationComponent);}@Overridepublic String getName() {return super.getName();}@Overridepublic String getDes() {return super.getDes();}// print方法,就是输出University 包含的学院@Overrideprotected void print() {System.out.println("--------------" + getName() + "--------------");//遍历 organizationComponents for (OrganizationComponent organizationComponent : organizationComponents) {organizationComponent.print();}}
}
package com.atguigu.composite;import java.util.ArrayList;
import java.util.List;public class College extends OrganizationComponent {//List 中 存放的DepartmentList<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();// 构造器public College(String name, String des) {super(name, des);}// 重写add@Overrideprotected void add(OrganizationComponent organizationComponent) {//  将来实际业务中,Colleage 的 add 和  University add 不一定完全一样organizationComponents.add(organizationComponent);}// 重写remove@Overrideprotected void remove(OrganizationComponent organizationComponent) {organizationComponents.remove(organizationComponent);}@Overridepublic String getName() {return super.getName();}@Overridepublic String getDes() {return super.getDes();}// print方法,就是输出University 包含的学院@Overrideprotected void print() {System.out.println("--------------" + getName() + "--------------");//遍历 organizationComponents for (OrganizationComponent organizationComponent : organizationComponents) {organizationComponent.print();}}
}
package com.atguigu.composite;public class Department extends OrganizationComponent {//没有集合public Department(String name, String des) {super(name, des);}//add , remove 就不用写了,因为他是叶子节点@Overridepublic String getName() {return super.getName();}@Overridepublic String getDes() {return super.getDes();}@Overrideprotected void print() {System.out.println(getName());}}

客户端 

package com.atguigu.composite;public class Client {public static void main(String[] args) {//从大到小创建对象 学校OrganizationComponent university = new University("清华大学", " 中国顶级大学 ");//创建 学院OrganizationComponent computerCollege = new College("计算机学院", " 计算机学院 ");OrganizationComponent infoEngineercollege = new College("信息工程学院", " 信息工程学院 ");//创建各个学院下面的系(专业)//给计算机学院添加专业computerCollege.add(new Department("软件工程", " 软件工程不错 "));computerCollege.add(new Department("网络工程", " 网络工程不错 "));computerCollege.add(new Department("计算机科学与技术", " 计算机科学与技术是老牌的专业 "));//给信息工程学院添加专业infoEngineercollege.add(new Department("通信工程", " 通信工程不好学 "));infoEngineercollege.add(new Department("信息工程", " 信息工程好学 "));//将学院加入到 学校university.add(computerCollege);university.add(infoEngineercollege);//university.print();infoEngineercollege.print();}}

12.7 组合模式在JDK集合的源码分析★

package com.atguigu.jdk;import java.util.HashMap;
import java.util.Map;public class Composite {public static void main(String[] args) {//说明//1. Map 就是一个抽象的构建 (类似我们的Component)//2. HashMap是一个中间的构建(Composite), 实现/继承了相关方法//   put, putall //3. Node 是 HashMap的静态内部类,类似Leaf叶子节点, 这里就没有put, putall//   static class Node<K,V> implements Map.Entry<K,V>Map<Integer,String> hashMap=new HashMap<Integer,String>();hashMap.put(0, "东游记");//直接存放叶子节点(Node)Map<Integer,String> map=new HashMap<Integer,String>();map.put(1, "西游记");map.put(2, "红楼梦"); //..hashMap.putAll(map);System.out.println(hashMap);}
}

12.8 组合模式的注意事项和细节

第13章 9外观模式(Facade)

13.1 影院管理项目

13.2 传统方式解决影院管理

13.3 传统方式解决影院管理问题分析

13.4 外观模式基本介绍

13.5 外观模式原理类图

13.6 外观模式解决影院管理

13.6.1 传统方式解决影院管理说明

13.6.2 外观模式应用实例

子系统6个

package com.atguigu.facade;public class DVDPlayer {//使用单例模式, 使用饿汉式private static DVDPlayer instance = new DVDPlayer();public static DVDPlayer getInstanc() {return instance;}public void on() {System.out.println(" dvd on ");}public void off() {System.out.println(" dvd off ");}public void play() {System.out.println(" dvd is playing ");}//....public void pause() {System.out.println(" dvd pause ..");}
}
package com.atguigu.facade;public class Popcorn {//使用单例模式, 使用饿汉式private static Popcorn instance = new Popcorn();public static Popcorn getInstance() {return instance;}public void on() {System.out.println(" popcorn on ");}public void off() {System.out.println(" popcorn ff ");}public void pop() {System.out.println(" popcorn is poping  ");}
}
package com.atguigu.facade;public class Projector {//使用单例模式, 使用饿汉式private static Projector instance = new Projector();public static Projector getInstance() {return instance;}public void on() {System.out.println(" Projector on ");}public void off() {System.out.println(" Projector ff ");}public void focus() {System.out.println(" Projector is Projector  ");}//...
}
package com.atguigu.facade;public class Screen {//使用单例模式, 使用饿汉式private static Screen instance = new Screen();public static Screen getInstance() {return instance;}public void up() {System.out.println(" Screen up ");}public void down() {System.out.println(" Screen down ");}
}
package com.atguigu.facade;public class Stereo {//使用单例模式, 使用饿汉式private static Stereo instance = new Stereo();public static Stereo getInstance() {return instance;}public void on() {System.out.println(" Stereo on ");}public void off() {System.out.println(" Screen off ");}public void up() {System.out.println(" Screen up.. ");}//...
}
package com.atguigu.facade;public class TheaterLight {//使用单例模式, 使用饿汉式private static TheaterLight instance = new TheaterLight();public static TheaterLight getInstance() {return instance;}public void on() {System.out.println(" TheaterLight on ");}public void off() {System.out.println(" TheaterLight off ");}public void dim() {System.out.println(" TheaterLight dim.. ");}public void bright() {System.out.println(" TheaterLight bright.. ");}
}

外观类

package com.atguigu.facade;public class HomeTheaterFacade {//定义各个子系统对象private TheaterLight theaterLight;private Popcorn popcorn;private Stereo stereo;private Projector projector;private Screen screen;private DVDPlayer dVDPlayer;//构造器public HomeTheaterFacade() {super();this.theaterLight = TheaterLight.getInstance();this.popcorn = Popcorn.getInstance();this.stereo = Stereo.getInstance();this.projector = Projector.getInstance();this.screen = Screen.getInstance();this.dVDPlayer = DVDPlayer.getInstanc();}//操作分成 4 步public void ready() {popcorn.on();popcorn.pop();screen.down();projector.on();stereo.on();dVDPlayer.on();theaterLight.dim();}public void play() {dVDPlayer.play();}public void pause() {dVDPlayer.pause();}public void end() {popcorn.off();theaterLight.bright();screen.up();projector.off();stereo.off();dVDPlayer.off();}}

客户端

package com.atguigu.facade;public class Client {public static void main(String[] args) {//这里直接调用。。 很麻烦HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();homeTheaterFacade.ready();homeTheaterFacade.play();homeTheaterFacade.end();}}

13.7 外观模式在MyBatis框架应用的源码分析★

13.8 外观模式的注意事项和细节

第14章 10享元模式(Flyweight)

14.1 展示网站项目需求

14.2 传统方案解决网站展现项目

14.3 传统方案解决网站展现项目-问题分析

14.4 享元模式基本介绍

14.5 享元模式的原理类图

14.6 内部状态和外部状态

14.7 享元模式解决网站展现项目

package com.atguigu.flyweight;public abstract class WebSite {public abstract void use(User user);//抽象方法
}
package com.atguigu.flyweight;//具体网站
public class ConcreteWebSite extends WebSite {//共享的部分,内部状态private String type = ""; //网站发布的形式(类型)//构造器public ConcreteWebSite(String type) {this.type = type;}@Overridepublic void use(User user) {System.out.println("网站的发布形式为:" + type + " 在使用中 .. 使用者是" + user.getName());}
}
package com.atguigu.flyweight;import java.util.HashMap;// 网站工厂类,根据需要返回压一个网站
public class WebSiteFactory {//集合, 充当池的作用private HashMap<String, ConcreteWebSite> pool = new HashMap<>();//根据网站的类型,返回一个网站, 如果没有就创建一个网站,并放入到池中,并返回public WebSite getWebSiteCategory(String type) {if(!pool.containsKey(type)) {//就创建一个网站,并放入到池中pool.put(type, new ConcreteWebSite(type));}return (WebSite)pool.get(type);}//获取网站分类的总数 (池中有多少个网站类型)public int getWebSiteCount() {return pool.size();}
}
package com.atguigu.flyweight;public class User {private String name;public User(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

客户端

package com.atguigu.flyweight;public class Client {public static void main(String[] args) {// 创建一个工厂类WebSiteFactory factory = new WebSiteFactory();// 客户要一个以新闻形式发布的网站WebSite webSite1 = factory.getWebSiteCategory("新闻");webSite1.use(new User("tom"));// 客户要一个以博客形式发布的网站WebSite webSite2 = factory.getWebSiteCategory("博客");webSite2.use(new User("jack"));// 客户要一个以博客形式发布的网站WebSite webSite3 = factory.getWebSiteCategory("博客");webSite3.use(new User("smith"));// 客户要一个以博客形式发布的网站WebSite webSite4 = factory.getWebSiteCategory("博客");webSite4.use(new User("king"));System.out.println("网站的分类共=" + factory.getWebSiteCount());}}

14.8 享元模式在JDK-Interger的应用源码分析★

测试案例

package com.atguigu.jdk;public class FlyWeight {public static void main(String[] args) {//如果 Integer.valueOf(x) x 在  -128 --- 127 直接,就是使用享元模式返回,如果不在//范围内,则仍然 new//小结://1. 在valueOf 方法中,先判断值是否在 IntegerCache 中,如果不在,就创建新的Integer(new), 否则,就直接从 缓存池返回//2. valueOf 方法,就使用到享元模式//3. 如果使用valueOf 方法得到一个Integer 实例,范围在 -128 - 127 ,执行速度比 new 快Integer x = Integer.valueOf(127); // 得到 x实例,类型 IntegerInteger y = new Integer(127); // 得到 y 实例,类型 IntegerInteger z = Integer.valueOf(127);//..Integer w = new Integer(127);System.out.println(x.equals(y)); // 大小,trueSystem.out.println(x == y ); //  falseSystem.out.println(x == z ); // trueSystem.out.println(w == x ); // falseSystem.out.println(w == y ); // falseInteger x1 = Integer.valueOf(200);Integer x2 = Integer.valueOf(200);System.out.println("x1==x2 " + (x1 == x2)); // false}}

源码追踪

 

14.9 享元模式的注意事项和细节

第15章 11代理模式(Proxy)★

15.1 代理模式的基本介绍

15.2 静态代理(staticproxy)

15.2.1 静态代码模式的基本介绍

15.2.2 应用实例

package com.atguigu.proxy.staticproxy;//接口
public interface ITeacherDao {void teach(); // 授课的方法
}
package com.atguigu.proxy.staticproxy;public class TeacherDao implements ITeacherDao {@Overridepublic void teach() {System.out.println(" 老师授课中  。。。。。");}
}
package com.atguigu.proxy.staticproxy;//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao{private ITeacherDao target; // 目标对象,通过接口来聚合//构造器public TeacherDaoProxy(ITeacherDao target) {this.target = target;}@Overridepublic void teach() {System.out.println("开始代理  完成某些操作。。。。。 ");//方法target.teach();System.out.println("提交。。。。。");//方法}}

客户端

package com.atguigu.proxy.staticproxy;public class Client {public static void main(String[] args) {//创建目标对象(被代理对象)TeacherDao teacherDao = new TeacherDao();//创建代理对象, 同时将被代理对象传递给代理对象TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);//通过代理对象,调用到被代理对象的方法//即:执行的是代理对象的方法,代理对象再去调用目标对象的方法 teacherDaoProxy.teach();}
}

15.2.3 静态代理优缺点

15.3 动态代理(dynamicproxy)

15.3.1 动态代理模式的基本介绍

15.3.2 JDK中生成代理对象的API

15.3.3 动态代理应用实例

package com.atguigu.proxy.dynamic;//接口
public interface ITeacherDao {void teach(); // 授课方法void sayHello(String name);
}
package com.atguigu.proxy.dynamic;public class TeacherDao implements ITeacherDao {@Overridepublic void teach() {System.out.println(" 老师授课中.... ");}@Overridepublic void sayHello(String name) {System.out.println("hello " + name);}}
package com.atguigu.proxy.dynamic;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyFactory {//维护一个目标对象 , Objectprivate Object target;//构造器 , 对target 进行初始化public ProxyFactory(Object target) {this.target = target;}//给目标对象 生成一个代理对象public Object getProxyInstance() {//说明/**  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)//1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定//2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型//3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入*/return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("JDK代理开始~~");//反射机制调用目标对象的方法Object returnVal = method.invoke(target, args);System.out.println("JDK代理提交");return returnVal;}});}}

客户端

package com.atguigu.proxy.dynamic;public class Client {public static void main(String[] args) {//创建目标对象ITeacherDao target = new TeacherDao();//给目标对象,创建代理对象, 可以转成 ITeacherDaoITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象System.out.println("proxyInstance=" + proxyInstance.getClass());//通过代理对象,调用目标对象的方法//proxyInstance.teach();proxyInstance.sayHello(" tom ");}}

源码追踪 

调用无参数的方法

调用有参数的方法 

15.4 Cglib代理

15.4.1 Cglib代理模式的基本介绍

15.4.2 Cglib代理模式实现步骤

15.4.3 Cglib代理模式应用实例

package com.atguigu.proxy.cglib;public class TeacherDao {public String teach() {System.out.println(" 老师授课中  , 我是cglib代理,不需要实现接口 ");return "hello";}
}
package com.atguigu.proxy.cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class ProxyFactory implements MethodInterceptor {//维护一个目标对象private Object target;//构造器,传入一个被代理的对象public ProxyFactory(Object target) {this.target = target;}//返回一个代理对象:  是 target 对象的代理对象public Object getProxyInstance() {//1. 创建一个工具类Enhancer enhancer = new Enhancer();//2. 设置父类enhancer.setSuperclass(target.getClass());//3. 设置回调函数enhancer.setCallback(this);//4. 创建子类对象,即代理对象return enhancer.create();}//重写  intercept 方法,会调用目标对象的方法@Overridepublic Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {System.out.println("Cglib代理模式 ~~ 开始");Object returnVal = method.invoke(target, args);System.out.println("Cglib代理模式 ~~ 提交");return returnVal;}}

客户端

package com.atguigu.proxy.cglib;public class Client {public static void main(String[] args) {//创建目标对象TeacherDao target = new TeacherDao();//获取到代理对象,并且将目标对象传递给代理对象TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();//执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用String res = proxyInstance.teach();System.out.println("res=" + res);}}

追踪源码

​​​​​​​

15.5 几种常见的代理模式介绍——几种变体

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/455173.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Nuvoton干货分享】开发应用篇 4 -- 8bit MCU Flash 操作

我们在进行实际开发设计中&#xff0c;难免需要进行数据存储&#xff0c;早期很多都是外接EEPROM来进行设计&#xff0c;但是需要增加成本。其实芯片内部的Flash也是可以当成数据存储空间的。本章节主要介绍新唐的8位机如何进行常量数据的存储操作。 一、存储空间划分 我这边…

力扣hot100--DFS/BFS

DFS/BFS 1. 79. 单词搜索 中等 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相…

2024 睿抗机器人开发者大赛(RAICOM)-【网络安全】CTF 部分WP

文章目录 一、前言二、MICS你是黑客么循环的压缩包Goodtime 三、WEBpy 四、Crypto变异凯撒RSAcrypto3 一、前言 WP不完整&#xff0c;仅供参考&#xff01; 除WEB&#xff0c;RE&#xff0c;PWN外&#xff0c;其余附件均已打包完毕 也是一个对MISC比较友好的一个比赛~ 123网…

鲸鱼优化算法(Whale Optimization Algorithm, WOA)原理与MATLAB例程

鲸鱼优化算法&#xff08;Whale Optimization Algorithm, WOA&#xff09;是一种基于鲸鱼捕食行为的智能优化算法。它模拟了座头鲸在狩猎时的“气泡网”捕食策略。 文章目录 1.适应度函数2. 更新公式2.1 突袭行为2.2 螺旋更新3.线性递减参数4. 边界处理 MATLAB 实现示例代码说明…

C语言程序设计:现代设计方法习题笔记《chapter3》

第一题 ​ 代码示例&#xff1a; #include<stdio.h>int main() {printf("Enter a date&#xff08;mm/dd/yyyy&#xff09;: ");int day, month, year;scanf_s("%d/%d/%d", &month, &day, &year);printf("%04d%02d%02d", yea…

一款好用的搜索软件——everthing(搜索比文件资源管理器快)

everthing官网链接 在官网选择下载 1.下载后双击打开 2.点击OK&#xff08;需要其他语言自己选择&#xff09; 3.选择安装位置&#xff08;路径最好别带中文和空格&#xff09; 继续点击下一步 4. 点击下一步 5.继续点击安装 6.然后就完成了 7.点击打开然后就可以搜索了

Elastic Stack简介

本文内容参考了田雪松老师编著的《Elastic Stack应用宝典》 从ELK到Elastic Stack ELK是三个单词的首字母缩写&#xff0c;即Elasticsearch、Logstash和Kibana。 Elasticsearch用于数据存储与检索Logstash用于数据传输与清洗Kibana则用于数据可视化等领域 Elasticsearch的第…

AnaTraf | 网络性能监控系统NPM:提升网络性能与业务连续性

AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 网络系统非常复杂&#xff0c;管理和维护它们也越来越具有挑战性。为了确保网络性能和业务的持续稳定运行&#xff0c;IT运维团队需要对网络进行实时监控、优化和快速排查故障。本文将围绕网络性能监控系统&…

raidrive 访问搭建的ftp服务报错超时的情况

尝试了很久&#xff0c;包括改用户权限和密码&#xff0c;后面根据ftp日志&#xff0c;查到用户登录是正常的 /var/log/vsftpd.log 就知道&#xff0c;不是密码问题也不是服务器端的问题&#xff0c;通过多次尝试发现是被动模式的问题&#xff0c;被动模式会通过其他端口进行交…

ChatGPT实现旅游推荐微信小程序

随着旅游行业的快速发展&#xff0c;个性化推荐已成为提升用户体验的重要手段。通过AI技术&#xff0c;提供一个智能旅游推荐小程序&#xff0c;使用户能够轻松获取定制化的旅行建议。 项目概述 项目目标 开发一个AI旅游推荐小程序&#xff0c;基于用户输入的旅行偏好&#…

前后端请求、返回数据的多种方式

Springboot项目的业务逻辑 &#x1f319;项目基本结构&#xff1a; 通常情况下&#xff0c;我们在搭建后端项目的时候&#xff0c;处理业务逻辑我们需要用到Controller,Service,Mapper(mybatis,mybatis-plus)&#xff0c;Entry各层之间的相互调用来完成&#xff0c;还有就是我…

Docker部署MySQL主从复制

1. 主从复制概念及优势 1.1 概念 MySQL主从复制是一种数据库复制技术&#xff0c;它允许将一个数据库服务器&#xff08;主服务器&#xff09;上的数据更改复制到一个或多个数据库服务器&#xff08;从服务器&#xff09;。这种技术在数据库管理和维护中扮演着重要的角色&…

Ubuntu 2张4090,显卡安装,无法双屏显示

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; Ubuntu20.04 安装nvidia显卡 在已经安装好nvidia显卡的情况下&#xff1a; 单屏幕无法修改屏幕分辨率 无法双屏显示 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 单屏幕无法…

【Origin科技绘图】最新Origin2024中文版软件安装教程

Origin是由OriginLab公司开发的一个科学绘图、数据分析软件,支持在MicrosoftWindows下运行。Origin支持各种各样的2D/3D图形。Origin中的数据分析功能包括统计,信号处理,曲线拟合以及峰值分析。Origin中的曲线拟合是采用基Levernberg-Marquardt算法(LMA)的非线性最小二乘法拟合…

理工科考研想考计算机,湖南大学、重大、哈工大威海、山东大学,该如何选择?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 计算机对理工科同学来说&#xff0c;还是性价比很高的&#xff0c;具有很大的优势&#xff01; 一、就业前景广阔 高需求行业 在当今数字化时代&#xff0c;计算机技术几乎渗透到了各个领域&#xff0c;无论是互联网…

LabVIEW提高开发效率技巧----插入式架构

随着LabVIEW项目规模的扩大和系统复杂性的增加&#xff0c;传统的单一代码架构难以应对后期维护和功能扩展的需求。插入式架构&#xff08;Plug-In Architecture&#xff09;作为一种模块化设计方式&#xff0c;通过动态加载和运行子VI&#xff0c;使系统功能更加灵活、模块化&…

Django从请求到响应

视图 一个视图函数&#xff0c;简称视图&#xff0c;是一个简单的Python函数 def view_name() 定义视图函数view_name() URL的常用配置 path函数&#xff1a; path(route,view,name,**kwargs) route&#xff1a;RUL匹配规则 view&#xff1a;视图函数 name&#xf…

【部署篇】RabbitMq-03集群模式部署

一、准备主机 准备3台主机用于rabbitmq部署&#xff0c;文章中是在centos7上安装部署rabbitmq3.8通过文章中介绍的方式可以同样在centos8、centos9上部署&#xff0c;只需下载对应的版本进行相同的操作。 主机IP角色说明192.168.128.31种子节点192.168.128.32普通节点192.16…

React 分装webSocket

背景 AI 实时对话 需要流式数据 React Hooks 写法。新建WebSocket.tsx 放在根目录components import { useCallback, useRef, useState } from react;type MessageHandler (message: MessageEvent) > void; type ErrorHandler (event: Event) > void;export functi…

技术成神之路:设计模式(二十二)命令模式

介绍 命令模式&#xff08;Command Pattern&#xff09;是一种行为设计模式&#xff0c;允许将请求&#xff08;命令&#xff09;封装为对象&#xff0c;从而使您可以使用不同的请求、队列或记录请求日志&#xff0c;以及支持可撤销操作。 1. 定义 命令模式将一个请求封装为一个…