beans.xml
单例设计模式一共有 **8 **种写法,后面我们会依次讲到饿汉式 两种
懒汉式 三种双重检查
静态内部类枚举
编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好
代码重用性 (即:相同功能的代码,不用多次编写)
可读性 (即:编程规范性, 便于其他程序员的阅读和理解)
可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护)
可靠性 (即:当我们增加新的功能后,对原来的功能没有影响)
使程序呈现高内聚,低耦合的特性分享金句:
设计模式包含了面向对象的精髓,“懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要”
Scott Mayers 在其巨著《Effective C++》就曾经说过:C++老手和 C++新手的区别就是前者手背上有很多伤疤
设计模式原则,其实就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础(即:设计模式为什么这样设计的依据)
对类来说的,即一个类应该只负责一项职责。如类 A 负责两个不同职责:职责 1,职责 2。当职责 1 需求变更而改变 A 时,可能造成职责 2 执行错误,所以需要将类 A 的粒度分解为 A1,A2
以交通工具案例讲解看老师代码演示
Vehicle 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 + " 在公路上运行 "); } } |
---|
RoadVehicle roadVehicle = new RoadVehicle(); roadVehicle.run(“摩托车”); roadVehicle.run(“汽车”); AirVehicle airVehicle = new AirVehicle(); airVehicle.run(“飞机”); } } //方案 2 的分析 //1. 遵守单一职责原则 //2. 但是这样做的改动很大,即将类分解,同时修改客户端 //3. 改进:直接修改 Vehicle 类,改动的代码会比较少=>方案 3 class 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 + “水中运行”); } } |
---|
package com.atguigu.principle.singleresponsibility; public class SingleResponsibility3 { public static void main(String[] args) { // TODO Auto-generated method stub Vehicle2 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. //… //… //… } |
---|
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
先看一张图:
来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法。
将接口 **Interface1 拆分为独立的几个接口(**这里我们拆分成 3 个接口),类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
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(); } } |
---|
来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法
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(); } } |
---|
依赖倒转原则(Dependence Inversion Principle)是指:
高层模块不应该依赖低层模块,二者都应该依赖其抽象
抽象不应该依赖细节,细节应该依赖抽象
依赖倒转(倒置)的中心思想是面向接口编程
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
请编程完成 Person 接收消息 的功能。
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()); } } |
---|
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()); } } |
---|
应用案例代码
构造方法传递应用案例代码
setter 方式传递
应用案例代码
package com.atguigu.principle.inversion.improve; public class DependencyPass { public static void main(String[] args) { // TODO Auto-generated method stub ChangHong 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 { @Override public void play() { // TODO Auto-generated method stub System.out.println(“长虹电视机,打开”); } } |
---|
继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低, 增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
问题提出:在编程中,如何正确的使用继承? => 里氏替换原则
里氏替换原则(Liskov Substitution Principle)在 1988 年,由麻省理工学院的以为姓里的女士提出的。
如果对每个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型T2 是类型 T1 的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。.
该看个程序, 思考下问题和解决思路
package com.atguigu.principle.liskov; public class Liskov { public static void main(String[] args) { // TODO Auto-generated method stub A 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-3 System.out.println(“1-8=” + b.func1(1, 8));// 1-8 System.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 stub A 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+3 |
---|
System.out.println(“1+8=” + b.func1(1, 8));// 1+8 System.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); } } |
---|
开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
一个软件实体如类,模块和函数应该对扩展开放**(对提供方),对修改关闭(对使用方)**。用抽象构建框架,用实现扩展细节。
当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
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; } } |
---|
方式 1 的改进的思路分析
思路:把创建 **Shape **类做成抽象类,并提供一个抽象的 **draw **方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承 Shape,并实现 draw 方法即可,使用方的代码就不需要修 -> 满足了开闭原则
改进后的代码:
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; } @Override public void draw() { // TODO Auto-generated method stub System.out.println(" 绘制矩形 “); } } class Circle extends Shape { Circle() { super.m_type = 2; } @Override public void draw() { // TODO Auto-generated method stub System.out.println(” 绘制圆形 "); } } |
---|
//新增画三角形 class Triangle extends Shape { Triangle() { super.m_type = 3; } @Override public void draw() { // TODO Auto-generated method stub System.out.println(" 绘制三角形 “); } } //新增一个图形 class OtherGraphic extends Shape { OtherGraphic() { super.m_type = 4; } @Override public void draw() { // TODO Auto-generated method stub System.out.println(” 绘制其它图形 "); } } |
---|
一个对象应该对其他对象保持最少的了解
类与类关系越密切,耦合度越大
迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外泄露任何信息
迪米特法则还有个更简单的定义:只与直接的朋友通信
直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
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 getAllEmployee() { List list = new ArrayList(); for (int i = 0; i < 10; i++) { //这里我们增加了 10 个员工到 list CollegeEmployee emp = new CollegeEmployee(); emp.setId("学院员工 id= " + i); list.add(emp); } return list; |
---|
} } //学校管理类 //分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager //CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则 class SchoolManager { //返回学校总部的员工 public List getAllEmployee() { List list = new ArrayList(); for (int i = 0; i < 5; i++) { //这里我们增加了 5 个员工到 list Employee 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 list1 = sub.getAllEmployee(); System.out.println("------------学院员工 “); for (CollegeEmployee e : list1) { System.out.println(e.getId()); } //获取到学校总部员工 List 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 getAllEmployee() { List list = new ArrayList(); |
---|
for (int i = 0; i < 10; i++) { //这里我们增加了 10 个员工到 list CollegeEmployee emp = new CollegeEmployee(); emp.setId(“学院员工 id= " + i); list.add(emp); } return list; } //输出学院员工的信息 public void printEmployee() { //获取到学院员工 List list1 = getAllEmployee(); System.out.println(”------------学院员工 "); for (CollegeEmployee e : list1) { System.out.println(e.getId()); } } } //学校管理类 //分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager //CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则 class SchoolManager { //返回学校总部的员工 public List getAllEmployee() { |
---|
List list = new ArrayList(); for (int i = 0; i < 5; i++) { //这里我们增加了 5 个员工到 list Employee emp = new Employee(); emp.setId(“学校总部员工 id= " + i); list.add(emp); } return list; } //该方法完成输出学校总部和学院员工信息(id) void printAllEmployee(CollegeManager sub) { //分析问题 //1. 将输出学院的员工方法,封装到 CollegeManager sub.printEmployee(); //获取到学校总部员工 List list2 = this.getAllEmployee(); System.out.println(”------------学校总部员工 "); for (Employee e : list2) { System.out.println(e.getId()); } } } |
---|
Eclipse 安装 UML插件(AmaterasUML).zip
AmaterasUML_1.3.4.rar
画 UML 图与写文章差不多,都是把自己的思想描述给别人看,关键在于思路和条理,UML 图分类:
类图是描述类与类之间的关系的,是 UML 图中最核心的
在讲解设计模式时,我们必然会使用类图,为了让学员们能够把设计模式学到位,需要先给大家讲解类图
温馨提示:如果已经掌握 UML 类图的学员,可以直接听设计模式的章节
public class Person{ //代码形式->类图private Integer id;
private String name;
public void setName(String name){ this.name=name;
}
public String getName(){ return name;
}
}
public class PersonServiceBean { private PersonDao personDao;//类public void save(Person person){}
public IDCard getIDCard(Integer personid){} public void modify(){
Department department = new Department();
}
}
public class PersonDao{} public class IDCard{} public class Person{} public class Department{}
public abstract class DaoSupport{ public void save(Object entity){
}
public void delete(Object id){
}
}
public class PersonServiceBean extends Daosupport{
}
实现关系实际上就是 **A **类实现 **B **接口,他是依赖关系的特例
public interface PersonService { public void delete(Interger id);
}
public class PersonServiceBean implements PersonService { public void delete(Interger id){}
}
=>类图
小结:
聚合关系(Aggregation)表示的是整体和部分的关系,整体与部分可以分开。聚合关系是关联关系的特例,所以他具有关联的导航性与多重性。
如:一台电脑由键盘(keyboard)、显示器(monitor),鼠标等组成;组成电脑的各个配件是可以从电脑上分离出来的,使用带空心菱形的实线来表示:
1. 应用实例
组合关系:也是整体与部分的关系,但是整体与部分不可以分开。
再看一个案例:在程序中我们定义实体:Person 与 IDCard、Head, 那么 Head 和 Person 就是 组合,IDCard 和
Person 就是聚合。
但是如果在程序中 Person 实体中定义了对 IDCard 进行级联删除,即删除 Person 时连同 IDCard 一起删除,那么 IDCard 和 Person 就是组合了.
public class Person{ private IDCard card; private Head head = new Head(); } public class IDCard{} public class Head{} |
---|
对应的类图:
案例 2
public class Computer { private Mouse mouse = new Mouse(); //鼠标可以和 computer 不能分离private Moniter moniter = new Moniter();//显示器可以和 Computer 不能分离public void setMouse(Mouse mouse) { this.mouse = mouse; } public void setMoniter(Moniter moniter) { this.moniter = moniter; } } public class Mouse { } public class Moniter { } 对应的类图 |
---|
第 1 层:刚开始学编程不久,听说过什么是设计模式
第 2 层:有很长时间的编程经验,自己写了很多代码,其中用到了设计模式,但是自己却不知道
第 3 层:学习过了设计模式,发现自己已经在使用了,并且发现了一些新的模式挺好用的
第 4 层:阅读了很多别人写的源码和框架,在其中看到别人设计模式,并且能够领会设计模式的精妙和带来的好处。
第 5 层:代码写着写着,自己都没有意识到使用了设计模式,并且熟练的写了出来。
设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通用解决方案,设计模式(Design pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式的本质提高 软件的维护性,通用性和扩展性,并降低软件的复杂度。
<<设计模式>> 是经典的书,作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称 “四人组 GOF”)
设计模式并不局限于某种语言,java,php,c++ 都有设计模式.
设计模式分为三种类型,共 **23 **种
注意:不同的书籍上对分类和名称略有差别
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法)。
比如 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象。SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,这是就会使用到单例模式。
单例模式有八种方式:
饿汉式(静态常量)应用实例步骤如下:
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); // 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; } } |
---|
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:在类装载的时候就完成实例化,没有达到 Lazy Loading 的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费
这种方式基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,在单例模式中大多数都是调用 getInstance 方法, 但是导致类装载的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 就没有达到 lazy loading 的效果
结论:这种单例模式可用,可能造成内存浪费
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); // 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; } } |
---|
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); // 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; } } |
---|
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); // 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; } } |
---|
不推荐使用
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); // true System.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; } } |
---|
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); // 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; } } |
---|
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~”); } } |
---|
单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、**session **工厂等)
看一个披萨的项目:要便于披萨种类的扩展,要便于维护
编写 OrderPizza.java 去订购需要的各种 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); // } |
---|
分析:修改代码可以接受,但是如果我们在其它的地方也有创建 Pizza 的代码,就意味着,也需要修改,而创建 Pizza
的代码,往往有多处。
思路:把创建 **Pizza **对象封装到一个类中,这样我们有新的 **Pizza **种类时,只需要修改该类就可,其它有创建到 Pizza
对象的代码就不需要修改了.-> 简单工厂模式
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; } } |
---|
//OrderPizza.java 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); // } //定义一个简单工厂对象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); |
---|
//输出 pizza if(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 “”; } } |
---|
} |
---|
披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒 pizza。
使用简单工厂模式,创建不同的简单工厂类,比如 BJPizzaSimpleFactory、LDPizzaSimpleFactory 等等.从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
使用工厂方法模式
1. 工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
2. 工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
1. 披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒 pizza
1. 思路分析图解
1. 看老师代码实现
//OrderPizza.java 类 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 { |
@Override Pizza 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 stub return 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 { |
@Override Pizza 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 stub return pizza; } } |
---|
使用抽象工厂模式来完成披萨项目.
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 { @Override public Pizza createPizza(String orderType) { System.out.println(“使用的是抽象工厂模式”); // TODO Auto-generated method stub Pizza 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 { @Override public 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.java 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) { // 订购 ok 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.jdk; import java.util.Calendar; public class Factory { public static void main(String[] args) { // TODO Auto-generated method stub // getInstance 是 Calendar 静态方法 Calendar cal = Calendar.getInstance(); // 注意月份下标从 0 开始,所以取月份要+1 System.out.println(“年:” + cal.get(Calendar.YEAR)); System.out.println(“月:” + (cal.get(Calendar.MONTH) + 1)); System.out.println(“日:” + cal.get(Calendar.DAY_OF_MONTH)); System.out.println(“时:” + cal.get(Calendar.HOUR_OF_DAY)); System.out.println(“分:” + cal.get(Calendar.MINUTE)); System.out.println(“秒:” + cal.get(Calendar.SECOND)); } } |
---|
//Calendar.java |
public static Calendar getInstance() { return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT)); } |
---|
private static Calendar createCalendar(TimeZone zone, Locale aLocale) //根据 TimeZone zone, locale 创建对应的实例 { 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; } |
---|
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10
只羊。
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); //… } } |
---|
思路:Java 中 Object 类是所有类的根类,Object 类提供了一个 clone()方法,该方法可以将一个 Java 对象复制一份,但是需要实现 clone 的Java 类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力 =>原型模式
基本介绍
使用原型模式改进传统方式,让程序具有更高的效率和扩展性。
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; } @Override public String toString() { return “Sheep [name=” + name + “, age=” + age + “, color=” + color + “, address=” + address + “]”; } //克隆该实例,使用默认的 clone 方法来完成 @Override protected Object clone() { Sheep sheep = null; try { sheep = (Sheep)super.clone(); } catch (Exception e) { // TODO: handle exception System.out.println(e.getMessage()); } |
---|
// TODO Auto-generated method stub return sheep; } } |
---|
package com.atguigu.prototype.improve; public class Client { public static void main(String[] args) { System.out.println(“原型模式完成对象的创建”); // TODO Auto-generated method stub Sheep 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()); } } |
---|
复制对象的所有基本数据类型的成员变量值
为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象**(包括对象的引用类型)**进行拷贝
深拷贝实现方式 1:重写 **clone **方法来实现深拷贝
深拷贝实现方式 2:通过对象序列化实现深拷贝(推荐)
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 完成即可 @Override protected 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 方法 @Override protected Object clone() throws CloneNotSupportedException { Object deep = null; //这里完成对基本数据类型(属性)和 String 的克隆 deep = super.clone(); //对引用类型的属性,进行单独处理 DeepProtoType deepProtoType = (DeepProtoType)deep; deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone(); // TODO Auto-generated method stub return 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 exception e.printStackTrace(); return null; } finally { //关闭流try { bos.close(); oos.close(); bis.close(); ois.close(); } catch (Exception e2) { // TODO: handle exception System.out.println(e2.getMessage()); } } } } |
---|
//Client.java package com.atguigu.prototype.deepclone; public class Client { |
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub DeepProtoType 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()); } } |
---|
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 { @Override public void buildBasic() { // TODO Auto-generated method stub System.out.println(" 普通房子打地基 "); } @Override public void buildWalls() { // TODO Auto-generated method stub |
System.out.println(" 普通房子砌墙 “); } @Override public void roofed() { // TODO Auto-generated method stub System.out.println(” 普通房子封顶 "); } } |
---|
package com.atguigu.builder; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub CommonHouse commonHouse = new CommonHouse(); commonHouse.build(); } } |
基本介绍
Product(产品角色): 一个具体的产品对象。
Builder(抽象建造者): 创建一个 Product 对象的各个部件指定的 接口**/**抽象类。
ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
Director(指挥者): 构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
建造者模式解决盖房需求应用实例
需要建房子:这一过程为打桩、砌墙、封顶。不管是普通房子也好,别墅也好都需要经历这些过程,下面我们使用建造者模式(Builder Pattern)来完成
思路分析图解(类图)
improve.zip
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(); |
---|
} } |
---|
package com.atguigu.builder.improve; 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(” 普通房子屋顶 "); } |
} |
---|
package com.atguigu.builder.improve; 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(” 高楼的透明屋顶 "); } } |
package com.atguigu.builder.improve; //产品->Product 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; } |
} |
---|
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 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(); } } |
---|
客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰, 也更方便使用程序来控制创建过程
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式.
抽象工厂模式 VS 建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品
泰国插座用的是两孔的(欧标),可以买个多功能转换插头 (适配器) ,这样就可以使用了。
基本介绍:Adapter 类,通过继承 src 类,实现 dst 类接口,完成 src->dst 的适配。
以生活中充电器的例子来讲解适配器,充电器本身相当于 Adapter,220V 交流电相当于 src (即被适配者),我们的目 dst(即 目标)是 5V 直流电
classadapter.zip
package com.atguigu.adapter.classadapter; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(" === 类适配器模式 ===="); Phone phone = new Phone(); phone.charging(new VoltageAdapter()); } } |
---|
package com.atguigu.adapter.classadapter; //适配接口 public interface IVoltage5V { public int output5V(); } |
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 Voltage220V { //输出 220V 的电压 public int output220V() { int src = 220; System.out.println(“电压=” + src + “伏”); return src; } } |
package com.atguigu.adapter.classadapter; //适配器类 |
public class VoltageAdapter extends Voltage220V implements IVoltage5V { @Override public int output5V() { // TODO Auto-generated method stub //获取到 220V 电压 int srcV = output220V(); int dstV = srcV / 44 ; //转成 5v return dstV; } } |
---|
基本思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解决兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src->dst 的适配
根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系。
对象适配器模式是适配器模式常用的一种
以生活中充电器的例子来讲解适配器,充电器本身相当于 Adapter,220V 交流电相当于 src (即被适配者),我们的目 dst(即目标)是 5V 直流电,使用对象适配器模式完成。
objectadapter.zip
package com.atguigu.adapter.objectadapter; |
---|
public class Client { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(" === 对象适配器模式 ===="); Phone phone = new Phone(); phone.charging(new VoltageAdapter(new Voltage220V())); } } |
---|
package com.atguigu.adapter.objectadapter; //适配接口 public interface IVoltage5V { public int output5V(); } |
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 Voltage220V { //输出 220V 的电压,不变 public int output220V() { int src = 220; System.out.println(“电压=” + src + “伏”); return src; } } |
package com.atguigu.adapter.objectadapter; //适配器类 public class VoltageAdapter implements IVoltage5V { private Voltage220V voltage220V; // 关联关系-聚合 |
//通过构造器,传入一个 Voltage220V 实例 public VoltageAdapter(Voltage220V voltage220v) { this.voltage220V = voltage220v; } @Override public 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; } } |
---|
根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承 src 的局限性问题,也不再要求 dst
必须是接口。
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() { //只需要去覆盖我们 需要使用 接口方法 @Override public void m1() { // TODO Auto-generated method stub System.out.println(“使用了 m1 的方法”); } }; absAdapter.m1(); } } |
---|
可以看到处理器的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用 Controller 方法,需要调用的时候就得不断是使用 if else 来进行判断是哪一种子类然后执行。那么如果后面要扩展 Controller, 就得修改原来的代码,这样违背了 OCP 原则。
springmvc.zip 源码:
对象适配器:以对象给到,在 Adapter 里,将 src 作为一个对象,持有接口适配器:以接口给到,在 Adapter 里,将 src 作为一个接口,实现
现在对不同手机类型的不同品牌实现操作编程(比如:开机、关机、上网,打电话等),如图:
基本介绍
充当桥接类
使用桥接模式改进传统方式,让程序具有搞好的扩展性,利用程序维护
1. 应用实例说明(和前面要求一样)
2. 使用桥接模式对应的类图
1. ![](https://img-blog.csdnimg.cn/img_convert/367d16c58843a497fa40c10a428eee63.png)代码
bridge.zip
package com.atguigu.bridge; |
---|
//接口 public interface Brand { void open(); void close(); void call(); } |
---|
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(); } } |
---|
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; 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; 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 Vivo implements Brand { @Override |
public void open() { // TODO Auto-generated method stub System.out.println(" Vivo 手机开机 “); } @Override public void close() { // TODO Auto-generated method stub System.out.println(” Vivo 手机关机 “); } @Override public void call() { // TODO Auto-generated method stub System.out.println(” Vivo 手机打电话 "); } } |
---|
package com.atguigu.bridge; public class XiaoMi implements Brand { @Override public void open() { // TODO Auto-generated method stub |
System.out.println(" 小米手机开机 “); } @Override public void close() { // TODO Auto-generated method stub System.out.println(” 小米手机关机 “); } @Override public void call() { // TODO Auto-generated method stub System.out.println(” 小米手机打电话 "); } } |
---|
桥接模式在 JDBC 的源码剖析
Driver,这些就可以当做实现接口类
桥接模式其它应用场景
对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用.
1. -JDBC 驱动程序
2. -银行转账系统
转账分类: 网上转账,柜台转账,AMT 转账
转账用户类型:普通用户,银卡用户,金卡用户…
1. -消息管理
消息类型:即时消息,延时消息
消息分类:手机短信,邮件消息,QQ 消息…
方案 1-解决星巴克咖啡订单问题分析
Drink 是一个抽象类,表示饮料
des 就是对咖啡的描述, 比如咖啡的名字
cost() 方法就是计算费用,Drink 类中做成一个抽象方法.
Decaf 就是单品咖啡, 继承 Drink, 并实现 cost
Espress && Milk 就是单品咖啡+调料, 这个组合很多
问题:这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸
1. 前面分析到方案 1 因为咖啡单品+调料组合会造成类的倍增,因此可以做改进,将调料内置到 Drink 类,这样就不会造成类数量过多。从而提高项目的维护性(如图)
1. 说明: milk,soy,chocolate 可以设计为 Boolean,表示是否要添加相应的调料.
1. 装饰者模式就像打包一个快递
主体:比如:陶瓷、衣服 (Component) // 被装饰者
包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)
1. Component 主体:比如类似前面的 Drink
2. ConcreteComponent 和 Decorator ConcreteComponent:具体的主体, 比如前面的各个单品咖啡
3. Decorator: 装饰者,比如各调料.
在如图的 Component 与 ConcreteComponent 之间,如果 ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。
咖啡订单项目包结构
decorator.zip
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 Coffee extends Drink { @Override public float cost() { // TODO Auto-generated method stub return super.getPrice(); } |
} |
---|
package com.atguigu.decorator; public class CoffeeBar { public static void main(String[] args) { // TODO Auto-generated method stub // 装饰者模式下的订单:2 份巧克力+一份牛奶的 LongBlack // 1. 点一份 LongBlack Drink 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()); } } |
---|
package com.atguigu.decorator; public class DeCaf extends Coffee { public DeCaf() { setDes(" 无因咖啡 "); setPrice(1.0f); } } |
---|
package com.atguigu.decorator; public class Decorator extends Drink { private Drink obj; public Decorator(Drink obj) { //组合 // TODO Auto-generated constructor stub this.obj = obj; } @Override public float cost() { // TODO Auto-generated method stub // getPrice 自己价格 return super.getPrice() + obj.cost(); } |
@Override public String getDes() { // TODO Auto-generated method stub // obj.getDes() 输出被装饰者的信息 return des + " " + getPrice() + " && " + obj.getDes(); } } |
---|
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(); | |
} |
|
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 Milk extends Decorator { public Milk(Drink obj) { super(obj); // TODO Auto-generated constructor stub setDes(" 牛奶 "); setPrice(2.0f); } } |
package com.atguigu.decorator; public class ShortBlack extends Coffee{ public ShortBlack() { setDes(" shortblack "); setPrice(4.0f); } |
} |
---|
package com.atguigu.decorator; public class Soy extends Decorator{ public Soy(Drink obj) { super(obj); // TODO Auto-generated constructor stub setDes(" 豆浆 "); setPrice(1.5f); } } |
Java 的 IO 结构,FilterInputStream 就是一个装饰者
源码说明
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{ // TODO Auto-generated method stub //说明 //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(); } } |
---|
编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。如图:
传统方案解决学校院系展示存在的问题分析
将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
实际上我们的要求是 :在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因
此这种方案,不能很好实现的管理的操作,比如对学院、系的添加,删除,遍历等
基本介绍
组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体**-**部分”的层次关系。
组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
这种类型的设计模式属于结构型模式。
组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象
对原理结构图的说明-即(组合模式的角色及职责)
应用实例要求
composite.zip
package com.atguigu.composite; |
---|
public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //从大到小创建对象 学校 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(); } } |
---|
package com.atguigu.composite; import java.util.ArrayList; import java.util.List; public class College extends OrganizationComponent { //List 中 存放的 Department List organizationComponents = new ArrayList(); // 构造器 public College(String name, String des) { super(name, des); // TODO Auto-generated constructor stub } // 重写 add @Override protected void add(OrganizationComponent organizationComponent) { // TODO Auto-generated method stub |
// 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样 organizationComponents.add(organizationComponent); } // 重写 remove @Override protected void remove(OrganizationComponent organizationComponent) { // TODO Auto-generated method stub organizationComponents.remove(organizationComponent); } @Override public String getName() { // TODO Auto-generated method stub return super.getName(); } @Override public String getDes() { // TODO Auto-generated method stub return super.getDes(); } // print 方法,就是输出 University 包含的学院 @Override protected void print() { |
---|
// TODO Auto-generated method stub 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); // TODO Auto-generated constructor stub } //add , remove 就不用写了,因为他是叶子节点 @Override |
public String getName() { // TODO Auto-generated method stub return super.getName(); } @Override public String getDes() { // TODO Auto-generated method stub return super.getDes(); } @Override protected void print() { // TODO Auto-generated method stub System.out.println(getName()); } } |
---|
package com.atguigu.composite; 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; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDes() { |
---|
return des; } public void setDes(String des) { 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 organizationComponents = new ArrayList(); // 构造器 public University(String name, String des) { super(name, des); |
// TODO Auto-generated constructor stub } // 重写 add @Override protected void add(OrganizationComponent organizationComponent) { // TODO Auto-generated method stub organizationComponents.add(organizationComponent); } // 重写 remove @Override protected void remove(OrganizationComponent organizationComponent) { // TODO Auto-generated method stub organizationComponents.remove(organizationComponent); } @Override public String getName() { // TODO Auto-generated method stub return super.getName(); } @Override public String getDes() { // TODO Auto-generated method stub |
---|
return super.getDes(); } // print 方法,就是输出 University 包含的学院 @Override protected void print() { // TODO Auto-generated method stub System.out.println(“--------------” + getName() + " "); //遍历 organizationComponents for (OrganizationComponent organizationComponent : organizationComponents) { organizationComponent.print(); } } } |
---|
组建一个家庭影院:
DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,其过程为: 直接用遥控器:统筹各设备开关
开爆米花机放下屏幕 开投影仪 开音响
开 DVD,选 dvd
去拿爆米花调暗灯光 播放
观影结束后,关闭各种设备
ready, play, pause, end ),用来访问子系统中的一群接口
基本介绍
facade.zip
package com.atguigu.facade; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //这里直接调用。。 很麻烦 HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(); homeTheaterFacade.ready(); homeTheaterFacade.play(); homeTheaterFacade.end(); |
---|
} } |
---|
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 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 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… "); } } |
---|
Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与 Facade 类交互,提高复用性
小型的外包项目,给客户 A 做一个产品展示网站,客户 A 的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同:
基本介绍
对原理图的说明-即(模式的角色及职责)
比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后,落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态
使用享元模式完成,前面提出的网站外包问题
flyweight.zip
package com.atguigu.flyweight; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub |
---|
// 创建一个工厂类 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()); |
---|
} } |
---|
package com.atguigu.flyweight; //具体网站 public class ConcreteWebSite extends WebSite { //共享的部分,内部状态 private String type = “”; //网站发布的形式(类型) //构造器 public ConcreteWebSite(String type) { this.type = type; } @Override public void use(User user) { // TODO Auto-generated method stub System.out.println(“网站的发布形式为:” + type + " 在使用中 … 使用者是" + user.getName()); } |
} |
---|
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 abstract class WebSite { public abstract void use(User user);//抽象方法 } |
---|
package com.atguigu.flyweight; import java.util.HashMap; // 网站工厂类,根据需要返回压一个网站 public class WebSiteFactory { //集合, 充当池的作用 private 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.jdk; public class FlyWeight { |
---|
public static void main(String[] args) { // TODO Auto-generated method stub //如果 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 实例,类型 Integer Integer y = new Integer(127); // 得到 y 实例,类型 Integer Integer z = Integer.valueOf(127);//… Integer w = new Integer(127); System.out.println(x.equals(y)); // 大小,true System.out.println(x == y ); // false System.out.println(x == z ); // true System.out.println(w == x ); // false System.out.println(w == y ); // false Integer x1 = Integer.valueOf(200); Integer x2 = Integer.valueOf(200); |
---|
System.out.println(“x1==x2” + (x1 == x2)); // false } } |
---|
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类
staticproxy.zip
package com.atguigu.proxy.staticproxy; public class Client { |
---|
public static void main(String[] args) { // TODO Auto-generated method stub //创建目标对象(被代理对象) TeacherDao teacherDao = new TeacherDao(); //创建代理对象, 同时将被代理对象传递给代理对象 TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao); //通过代理对象,调用到被代理对象的方法 //即:执行的是代理对象的方法,代理对象再去调用目标对象的方法teacherDaoProxy.teach(); } } |
---|
package com.atguigu.proxy.staticproxy; //接口 public interface ITeacherDao { void teach(); // 授课的方法 } |
package com.atguigu.proxy.staticproxy; public class TeacherDao implements ITeacherDao { |
@Override public void teach() { // TODO Auto-generated method stub System.out.println(" 老师授课中 。。。。。"); } } |
---|
package com.atguigu.proxy.staticproxy; //代理对象,静态代理 public class TeacherDaoProxy implements ITeacherDao{ private ITeacherDao target; // 目标对象,通过接口来聚合 //构造器 public TeacherDaoProxy(ITeacherDao target) { this.target = target; } @Override public void teach() { // TODO Auto-generated method stub System.out.println("开始代理 完成某些操作。。。。。 ");//方法target.teach(); System.out.println(“提交。。。。。”);//方法 |
} } |
---|
将前面的静态代理改进成动态代理模式(即:JDK 代理模式)
dynamic.zip
package com.atguigu.proxy.dynamic; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建目标对象 ITeacherDao target = new TeacherDao(); //给目标对象,创建代理对象, 可以转成 ITeacherDao |
---|
ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance(); // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象 System.out.println(“proxyInstance=” + proxyInstance.getClass()); //通过代理对象,调用目标对象的方法 //proxyInstance.teach(); proxyInstance.sayHello(" tom "); } } |
---|
package com.atguigu.proxy.dynamic; //接口 public interface ITeacherDao { void teach(); // 授课方法 void sayHello(String name); } |
package com.atguigu.proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; |
import java.lang.reflect.Proxy; public class ProxyFactory { //维护一个目标对象 , Object private 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() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println(“JDK 代理开始~~”); //反射机制调用目标对象的方法 Object returnVal = method.invoke(target, args); System.out.println(“JDK 代理提交”); return returnVal; } }); } } |
---|
package com.atguigu.proxy.dynamic; public class TeacherDao implements ITeacherDao { @Override public void teach() { |
// TODO Auto-generated method stub System.out.println(" 老师授课中 "); } @Override public void sayHello(String name) { // TODO Auto-generated method stub System.out.println("hello " + name); } } |
---|
将前面的案例用 Cglib 代理模式实现
cglib.zip
package com.atguigu.proxy.cglib; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建目标对象 TeacherDao target = new TeacherDao(); //获取到代理对象,并且将目标对象传递给代理对象 TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance(); //执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用 String res = proxyInstance.teach(); System.out.println(“res=” + res); } } |
---|
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 方法,会调用目标对象的方法 |
---|
@Override public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub System.out.println(“Cglib 代理模式 ~~ 开始”); Object returnVal = method.invoke(target, args); System.out.println(“Cglib 代理模式 ~~ 提交”); return returnVal; } } |
---|
package com.atguigu.proxy.cglib; public class TeacherDao { public String teach() { System.out.println(" 老师授课中 , 我是 cglib 代理,不需要实现接口 "); return “hello”; } } |
内网通过代理穿透防火墙,实现对公网的访问。
比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok,如果取不到资源,再到公网或者数据库取,然后缓存。
远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。
编写制作豆浆的程序,说明如下:
基本介绍
编写制作豆浆的程序,说明如下:
制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎通过添加不同的配料,可以制作出不同口味的豆浆
选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的(红豆、花生豆浆。。。)
template.zip
package com.atguigu.template; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //制作红豆豆浆 System.out.println("----制作红豆豆浆 “); SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk(); redBeanSoyaMilk.make(); System.out.println(”----制作花生豆浆 "); SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk(); peanutSoyaMilk.make(); |
---|
} } |
---|
package com.atguigu.template; public class PeanutSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub System.out.println(" 加入上好的花生 "); } } |
package com.atguigu.template; public class RedBeanSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub System.out.println(" 加入上好的红豆 "); } |
} |
---|
package com.atguigu.template; //抽象类,表示豆浆 public abstract class SoyaMilk { //模板方法, make , 模板方法可以做成 final , 不让子类去覆盖. final void make() { select(); addCondiments(); soak(); beat(); } //选材料 void select() { System.out.println("第一步:选择好的新鲜黄豆 "); } //添加不同的配料, 抽象方法, 子类具体实现 abstract void addCondiments(); //浸泡 |
void soak() { System.out.println("第三步, 黄豆和配料开始浸泡, 需要 3 小时 "); } void beat() { System.out.println("第四步:黄豆和配料放到豆浆机去打碎 "); } } |
---|
improve.zip
package com.atguigu.template.improve; //抽象类,表示豆浆 public abstract class SoyaMilk { //模板方法, make , 模板方法可以做成 final , 不让子类去覆盖. final void make() { |
---|
select(); if(customerWantCondiments()) { addCondiments(); } soak(); beat(); } //选材料 void select() { System.out.println("第一步:选择好的新鲜黄豆 "); } //添加不同的配料, 抽象方法, 子类具体实现 abstract void addCondiments(); //浸泡 void soak() { System.out.println("第三步, 黄豆和配料开始浸泡, 需要 3 小时 "); } void beat() { System.out.println("第四步:黄豆和配料放到豆浆机去打碎 "); } //钩子方法,决定是否需要添加配料boolean customerWantCondiments() { return true; |
---|
} } |
---|
就可以控制全部智能家电。
我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计
Invoker 是调用者(将军),Receiver 是被调用者(士兵),MyCommand 是命令,实现了 Command 接口,持有接收对象
应用实例要求
command.zip
package com.atguigu.command; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //使用命令设计模式,完成通过遥控器,对电灯的操作 //创建电灯的对象(接受者) LightReceiver lightReceiver = new LightReceiver(); //创建电灯相关的开关命令 LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver); |
---|
LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver); //需要一个遥控器 RemoteController remoteController = new RemoteController(); //给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作 remoteController.setCommand(0, lightOnCommand, lightOffCommand); System.out.println(“--------按下灯的开按钮 “); remoteController.onButtonWasPushed(0); System.out.println(”--------按下灯的关按钮 “); remoteController.offButtonWasPushed(0); System.out.println(”--------按下撤销按钮 “); remoteController.undoButtonWasPushed(); System.out.println(”=使用遥控器操作电视机==”); TVReceiver tvReceiver = new TVReceiver(); TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver); TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver); //给我们的遥控器设置命令, 比如 no = 1 是电视机的开和关的操作 remoteController.setCommand(1, tvOnCommand, tvOffCommand); |
---|
System.out.println("--------按下电视机的开按钮 “); remoteController.onButtonWasPushed(1); System.out.println(”--------按下电视机的关按钮 “); remoteController.offButtonWasPushed(1); System.out.println(”--------按下撤销按钮 "); remoteController.undoButtonWasPushed(); } } |
---|
package com.atguigu.command; //创建命令接口 public interface Command { //执行动作(操作) public void execute(); //撤销动作(操作) public void undo(); } |
package com.atguigu.command; public class LightOffCommand implements Command { |
// 聚合 LightReceiver LightReceiver light; // 构造器 public LightOffCommand(LightReceiver light) { super(); this.light = light; } @Override public void execute() { // TODO Auto-generated method stub // 调用接收者的方法 light.off(); } @Override public void undo() { // TODO Auto-generated method stub // 调用接收者的方法 light.on(); } } |
---|
package com.atguigu.command; public class LightOnCommand implements Command { //聚合 LightReceiver LightReceiver light; //构造器 public LightOnCommand(LightReceiver light) { super(); this.light = light; } @Override public void execute() { // TODO Auto-generated method stub //调用接收者的方法light.on(); } @Override public void undo() { // TODO Auto-generated method stub |
---|
//调用接收者的方法light.off(); } } |
---|
package com.atguigu.command; public class LightReceiver { public void on() { System.out.println(" 电灯打开了… “); } public void off() { System.out.println(” 电灯关闭了… "); } } |
package com.atguigu.command; /** - 没有任何命令,即空执行: 用于初始化每个按钮, 当调用空命令时,对象什么都不做 - 其实,这样是一种设计模式, 可以省掉对空判断 - @author Administrator |
*/ public class NoCommand implements Command { @Override public void execute() { // TODO Auto-generated method stub } @Override public void undo() { // TODO Auto-generated method stub } } |
---|
package com.atguigu.command; public class RemoteController { // 开 按钮的命令数组Command[] onCommands; Command[] offCommands; // 执行撤销的命令 |
Command undoCommand; // 构造器,完成对按钮初始化 public RemoteController() { onCommands = new Command[5]; offCommands = new Command[5]; for (int i = 0; i < 5; i++) { onCommands[i] = new NoCommand(); offCommands[i] = new NoCommand(); } } // 给我们的按钮设置你需要的命令 public void setCommand(int no, Command onCommand, Command offCommand) { onCommands[no] = onCommand; offCommands[no] = offCommand; } // 按下开按钮 public void onButtonWasPushed(int no) { // no 0 // 找到你按下的开的按钮, 并调用对应方法 onCommands[no].execute(); // 记录这次的操作,用于撤销 |
---|
undoCommand = onCommands[no]; | |
---|---|
} |
|
// 按下开按钮 |
|
public void offButtonWasPushed(int no) { // no 0 | |
// 找到你按下的关的按钮, 并调用对应方法 | |
offCommands[no].execute(); | |
// 记录这次的操作,用于撤销 | |
undoCommand = offCommands[no]; | |
} |
|
// 按下撤销按钮 |
|
public void undoButtonWasPushed() { | |
undoCommand.undo(); | |
} | |
} |
|
package com.atguigu.command; public class TVOffCommand implements Command { // 聚合 TVReceiver |
TVReceiver tv; | |
---|---|
// 构造器 |
|
public TVOffCommand(TVReceiver tv) { | |
super(); | |
this.tv = tv; | |
} | |
@Override |
|
public void execute() { | |
// TODO Auto-generated method stub | |
// 调用接收者的方法 | |
tv.off(); | |
} | |
@Override |
|
public void undo() { | |
// TODO Auto-generated method stub | |
// 调用接收者的方法 | |
tv.on(); | |
} | |
} | |
package com.atguigu.command; public class TVOnCommand implements Command { |
// 聚合 TVReceiver TVReceiver tv; // 构造器 public TVOnCommand(TVReceiver tv) { super(); this.tv = tv; } @Override public void execute() { // TODO Auto-generated method stub // 调用接收者的方法 tv.on(); } @Override public void undo() { // TODO Auto-generated method stub // 调用接收者的方法 tv.off(); } } |
---|
package com.atguigu.command; public class TVReceiver { public void on() { System.out.println(" 电视机打开了… “); } public void off() { System.out.println(” 电视机关闭了… "); } } |
---|
完成测评系统需求
访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
主要将数据结构与数据操作分离,解决 数据结构和操作耦合性问题
访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口
访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时
需要避免让这些操作"污染"这些对象的类,可以选用访问者模式解决
即(访问者模式的角色及职责)
应用实例要求
visitor.zip
package com.atguigu.visitor; public abstract class Action { //得到男性 的测评 public abstract void getManResult(Man man); |
---|
//得到女的 测评 public abstract void getWomanResult(Woman woman); } |
---|
package com.atguigu.visitor; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建 ObjectStructure ObjectStructure objectStructure = new ObjectStructure(); objectStructure.attach(new Man()); objectStructure.attach(new Woman()); //成功 Success success = new Success(); objectStructure.display(success); System.out.println(“===============”); Fail fail = new Fail(); objectStructure.display(fail); |
System.out.println(“=给的是待定的测评==”); Wait wait = new Wait(); objectStructure.display(wait); } } |
---|
package com.atguigu.visitor; public class Fail extends Action { @Override public void getManResult(Man man) { // TODO Auto-generated method stub System.out.println(" 男人给的评价该歌手失败 !“); } @Override public void getWomanResult(Woman woman) { // TODO Auto-generated method stub System.out.println(” 女人给的评价该歌手失败 !"); } } |
package com.atguigu.visitor; public class Man extends Person { @Override public void accept(Action action) { // TODO Auto-generated method stub action.getManResult(this); } } |
---|
package com.atguigu.visitor; import java.util.LinkedList; import java.util.List; //数据结构,管理很多人(Man , Woman) public class ObjectStructure { //维护了一个集合 private List persons = new LinkedList<>(); //增加到 list public void attach(Person p) { persons.add§; |
} //移除 public void detach(Person p) { persons.remove§; } //显示测评情况 public void display(Action action) { for(Person p: persons) { p.accept(action); } } } |
---|
package com.atguigu.visitor; public abstract class Person { //提供一个方法,让访问者可以访问public abstract void accept(Action action); } |
package com.atguigu.visitor; public class Success extends Action { |
@Override public void getManResult(Man man) { // TODO Auto-generated method stub System.out.println(" 男人给的评价该歌手很成功 !“); } @Override public void getWomanResult(Woman woman) { // TODO Auto-generated method stub System.out.println(” 女人给的评价该歌手很成功 !"); } } |
---|
package com.atguigu.visitor; public class Wait extends Action { @Override public void getManResult(Man man) { // TODO Auto-generated method stub System.out.println(" 男人给的评价是该歌手待定 …"); } @Override public void getWomanResult(Woman woman) { |
// TODO Auto-generated method stub System.out.println(" 女人给的评价是该歌手待定 …"); } } |
---|
package com.atguigu.visitor; //说明 //1. 这里我们使用到了双分派, 即首先在客户端程序中,将具体状态作为参数传递 Woman 中(第一次分派) //2. 然后 Woman 类调用作为参数的 “具体方法” 中方法 getWomanResult, 同时将自己(this)作为参数 // 传入,完成第二次的分派 public class Woman extends Person{ @Override public void accept(Action action) { // TODO Auto-generated method stub action.getWomanResult(this); } } |
-上面提到了双分派,所谓双分派是指不管类怎么变化,我们都能找到期望的方法运行。双分派意味着得到执行的操作取决于请求的种类和两个接收者的类型
编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。如图:
传统的方式的问题分析
将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
实际上我们的要求是 :在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因此这种方案,不能很好实现的遍历的操作
解决方案:=> 迭代器模式
基本介绍
编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。
iterator.zip
package com.atguigu.iterator; import java.util.ArrayList; import java.util.List; |
---|
public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建学院 List collegeList = new ArrayList(); ComputerCollege computerCollege = new ComputerCollege(); InfoCollege infoCollege = new InfoCollege(); collegeList.add(computerCollege); //collegeList.add(infoCollege); OutPutImpl outPutImpl = new OutPutImpl(collegeList); outPutImpl.printCollege(); } } |
---|
package com.atguigu.iterator; import java.util.Iterator; public interface College { |
public String getName(); //增加系的方法 public void addDepartment(String name, String desc); //返回一个迭代器,遍历 public Iterator createIterator(); } |
---|
package com.atguigu.iterator; import java.util.Iterator; public class ComputerCollege implements College { Department[] departments; int numOfDepartment = 0 ;// 保存当前数组的对象个数 public ComputerCollege() { departments = new Department[5]; addDepartment(“Java 专业”, " Java 专业 "); addDepartment(“PHP 专业”, " PHP 专业 "); addDepartment(“大数据专业”, " 大数据专业 "); } |
@Override public String getName() { // TODO Auto-generated method stub return “计算机学院”; } @Override public void addDepartment(String name, String desc) { // TODO Auto-generated method stub Department department = new Department(name, desc); departments[numOfDepartment] = department; numOfDepartment += 1; } @Override public Iterator createIterator() { // TODO Auto-generated method stub return new ComputerCollegeIterator(departments); } } |
---|
package com.atguigu.iterator; |
import java.util.Iterator; public class ComputerCollegeIterator implements Iterator { //这里我们需要 Department 是以怎样的方式存放=>数组 Department[] departments; int position = 0; //遍历的位置 public ComputerCollegeIterator(Department[] departments) { this.departments = departments; } //判断是否还有下一个元素@Override public boolean hasNext() { // TODO Auto-generated method stub if(position >= departments.length || departments[position] == null) { return false; }else { return true; } |
---|
} @Override public Object next() { // TODO Auto-generated method stub Department department = departments[position]; position += 1; return department; } //删除的方法,默认空实现public void remove() { } } |
---|
package com.atguigu.iterator; //系 public class Department { private String name; private String desc; public Department(String name, String desc) { super(); |
this.name = name; | |
---|---|
this.desc = desc; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public String getDesc() { | |
return desc; | |
} | |
public void setDesc(String desc) { | |
this.desc = desc; | |
} | |
} |
|
package com.atguigu.iterator; import java.util.Iterator; import java.util.List; public class InfoColleageIterator implements Iterator { |
List departmentList; // 信息工程学院是以 List 方式存放系 int index = -1;//索引 public InfoColleageIterator(List departmentList) { this.departmentList = departmentList; } //判断 list 中还有没有下一个元素 @Override public boolean hasNext() { // TODO Auto-generated method stub if(index >= departmentList.size() - 1) { return false; } else { index += 1; return true; } } @Override public Object next() { // TODO Auto-generated method stub return departmentList.get(index); |
---|
} //空实现 remove public void remove() { } } |
---|
package com.atguigu.iterator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class InfoCollege implements College { List departmentList; public InfoCollege() { departmentList = new ArrayList(); addDepartment(“信息安全专业”, " 信息安全专业 "); addDepartment(“网络安全专业”, " 网络安全专业 "); addDepartment(“服务器安全专业”, " 服务器安全专业 "); } |
@Override public String getName() { // TODO Auto-generated method stub return “信息工程学院”; } @Override public void addDepartment(String name, String desc) { // TODO Auto-generated method stub Department department = new Department(name, desc); departmentList.add(department); } @Override public Iterator createIterator() { // TODO Auto-generated method stub return new InfoColleageIterator(departmentList); } } |
---|
package com.atguigu.iterator; import java.util.Iterator; import java.util.List; |
public class OutPutImpl { //学院集合 List collegeList; public OutPutImpl(List collegeList) { this.collegeList = collegeList; } //遍历所有学院,然后调用 printDepartment 输出各个学院的系 public void printCollege() { //从 collegeList 取出所有学院, Java 中的 List 已经实现 Iterator Iterator iterator = collegeList.iterator(); while(iterator.hasNext()) { //取出一个学院 College college = iterator.next(); System.out.println(“=== “+college.getName() +”=====” ); printDepartment(college.createIterator()); //得到对应迭代器 } } //输出 学院输出 系 |
---|
public void printDepartment(Iterator iterator) { while(iterator.hasNext()) { Department d = (Department)iterator.next(); System.out.println(d.getName()); } } } |
---|
每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
observer.zip
package com.atguigu.observer; public class Client { public static void main(String[] args) { //创建接入方 currentConditions CurrentConditions currentConditions = new CurrentConditions(); //创建 WeatherData 并将 接入方 currentConditions 传递到 WeatherData 中 WeatherData weatherData = new WeatherData(currentConditions); //更新天气情况weatherData.setData(30, 150, 40); //天气情况变化 System.out.println(“天气情况变化=”); weatherData.setData(40, 160, 20); } } |
---|
package com.atguigu.observer; /** |
|
- 显示当前天气情况(可以理解成是气象站自己的网站)
- @author Administrator
/ public class CurrentConditions { // 温度,气压,湿度private float temperature; private float pressure; private float humidity; //更新 天气情况,是由 WeatherData 来调用,我使用推送模式 public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } //显示 public void display() { System.out.println(“Today mTemperature: " + temperature + "”); System.out.println(“Today mPressure: " + pressure + "”); System.out.println(“Today mHumidity: " + humidity + "”); } } |
---|
| package com.atguigu.observer;
/**
- 类是核心
- 1. 包含最新的天气情况信息
- 2. 含有 CurrentConditions 对象
- 3. 当数据有更新时,就主动的调用 CurrentConditions 对象 update 方法(含 display), 这样他们(接入方)就看到最新的信息
- @author Administrator
/ public class WeatherData { private float temperatrue; private float pressure; private float humidity; private CurrentConditions currentConditions; //加入新的第三方 public WeatherData(CurrentConditions currentConditions) { this.currentConditions = currentConditions; } public float getTemperature() { return temperatrue; } |
---|
public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() { //调用 接入方的 update currentConditions.update(getTemperature(), getPressure(), getHumidity()); } //当数据有更新时,就调用 setData public void setData(float temperature, float pressure, float humidity) { this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; //调用 dataChange, 将最新的信息 推送给 接入方 currentConditions dataChange(); } } |
---|
//在 WeatherData 中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到 dataChange, 不利于维护,也不是动态加入
public void dataChange() {
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}
Observer:接收输入
观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject
通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户时 Observer,是多的一方。
1. 代码实现
improve.zip
package com.atguigu.observer.improve; public class BaiduSite implements Observer { // 温度,气压,湿度private float temperature; private float pressure; private float humidity; // 更新 天气情况,是由 WeatherData 来调用,我使用推送模式 public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; |
---|
this.pressure = pressure; this.humidity = humidity; display(); } // 显示 public void display() { System.out.println(“=百度网站==”); System.out.println(“百度网站 气温 : " + temperature + "”); System.out.println(“百度网站 气压: " + pressure + "”); System.out.println(“百度网站 湿度: " + humidity + "”); } } |
---|
package com.atguigu.observer.improve; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建一个 WeatherData WeatherData weatherData = new WeatherData(); //创建观察者 CurrentConditions currentConditions = new CurrentConditions(); |
BaiduSite baiduSite = new BaiduSite(); //注册到 weatherData weatherData.registerObserver(currentConditions); weatherData.registerObserver(baiduSite); //测试 System.out.println(“通知各个注册的观察者, 看看信息”); weatherData.setData(10f, 100f, 30.3f); weatherData.removeObserver(currentConditions); //测试System.out.println(); System.out.println(“通知各个注册的观察者, 看看信息”); weatherData.setData(10f, 100f, 30.3f); } } |
---|
package com.atguigu.observer.improve; public class CurrentConditions implements Observer { // 温度,气压,湿度 private float temperature; |
private float pressure; private float humidity; // 更新 天气情况,是由 WeatherData 来调用,我使用推送模式 public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // 显示 public void display() { System.out.println(“Today mTemperature: " + temperature + "”); System.out.println(“Today mPressure: " + pressure + "”); System.out.println(“Today mHumidity: " + humidity + "”); } } |
---|
package com.atguigu.observer.improve; //观察者接口,有观察者来实现public interface Observer { public void update(float temperature, float pressure, float humidity); } |
package com.atguigu.observer.improve; //接口, 让 WeatherData 来实现 public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); } |
package com.atguigu.observer.improve; import java.util.ArrayList; /** - 类是核心 - 1. 包含最新的天气情况信息 - 2. 含有 观察者集合,使用 ArrayList 管理 - 3. 当数据有更新时,就主动的调用 ArrayList, 通知所有的(接入方)就看到最新的信息 - @author Administrator |
/ public class WeatherData implements Subject { private float temperatrue; private float pressure; |
private float humidity; //观察者集合 private ArrayList observers; //加入新的第三方 public WeatherData() { observers = new ArrayList(); } public float getTemperature() { return temperatrue; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() { //调用 接入方的 update notifyObservers(); |
---|
} //当数据有更新时,就调用 setData public void setData(float temperature, float pressure, float humidity) { this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; //调用 dataChange, 将最新的信息 推送给 接入方 currentConditions dataChange(); } //注册一个观察者@Override public void registerObserver(Observer o) { // TODO Auto-generated method stub observers.add(o); } //移除一个观察者@Override public void removeObserver(Observer o) { // TODO Auto-generated method stub if(observers.contains(o)) { observers.remove(o); } } |
---|
//遍历所有的观察者,并通知@Override public void notifyObservers() { // TODO Auto-generated method stub for(int i = 0; i < observers.size(); i++) { observers.get(i).update(this.temperatrue, this.pressure, this.humidity); } } } |
---|
传统的方式的问题分析
当各电器对象有多种状态改变时,相互之间的调用关系会比较复杂
各个电器对象彼此联系,你中有我,我中有你,不利于松耦合.
各个电器对象之间所传递的消息(参数),容易混乱
当系统增加一个新的电器对象时,或者执行流程改变时,代码的可维护性、扩展性都不理想 考虑中介者模式
基本介绍
HashMap,并接受某个同事对象消息,完成相应的任务
完成前面的智能家庭的项目,使用中介者模式
smarthouse.zip
package com.atguigu.mediator.smarthouse; //具体的同事类 public class Alarm extends Colleague { //构造器 public Alarm(Mediator mediator, String name) { |
---|
super(mediator, name); // TODO Auto-generated constructor stub //在创建 Alarm 同事对象时,将自己放入到 ConcreteMediator 对象中[集合] mediator.Register(name, this); } public void SendAlarm(int stateChange) { SendMessage(stateChange); } @Override public void SendMessage(int stateChange) { // TODO Auto-generated method stub //调用的中介者对象的 getMessage this.GetMediator().GetMessage(stateChange, this.name); } } |
---|
package com.atguigu.mediator.smarthouse; public class ClientTest { public static void main(String[] args) { //创建一个中介者对象 Mediator mediator = new ConcreteMediator(); |
//创建 Alarm 并且加入到 ConcreteMediator 对象的 HashMap Alarm alarm = new Alarm(mediator, “alarm”); //创建了 CoffeeMachine 对象,并 且加入到 ConcreteMediator 对象的 HashMap CoffeeMachine coffeeMachine = new CoffeeMachine(mediator, “coffeeMachine”); //创建 Curtains , 并 且加入到 ConcreteMediator 对象的 HashMap Curtains curtains = new Curtains(mediator, “curtains”); TV tV = new TV(mediator, “TV”); //让闹钟发出消息alarm.SendAlarm(0); coffeeMachine.FinishCoffee(); alarm.SendAlarm(1); } } |
---|
package com.atguigu.mediator.smarthouse; public class CoffeeMachine extends Colleague { public CoffeeMachine(Mediator mediator, String name) { super(mediator, name); |
// TODO Auto-generated constructor stub mediator.Register(name, this); } @Override public void SendMessage(int stateChange) { // TODO Auto-generated method stub this.GetMediator().GetMessage(stateChange, this.name); } public void StartCoffee() { System.out.println(“It’s time to startcoffee!”); } public void FinishCoffee() { System.out.println(“After 5 minutes!”); System.out.println(“Coffee is ok!”); SendMessage(0); } } |
---|
package com.atguigu.mediator.smarthouse; //同事抽象类 public abstract class Colleague { |
private Mediator mediator; public String name; public Colleague(Mediator mediator, String name) { this.mediator = mediator; this.name = name; } public Mediator GetMediator() { return this.mediator; } public abstract void SendMessage(int stateChange); } |
---|
package com.atguigu.mediator.smarthouse; import java.util.HashMap; //具体的中介者类 public class ConcreteMediator extends Mediator { //集合,放入所有的同事对象 private HashMap |
public ConcreteMediator() { colleagueMap = new HashMap } @Override public void Register(String colleagueName, Colleague colleague) { // TODO Auto-generated method stub colleagueMap.put(colleagueName, colleague); // TODO Auto-generated method stub if (colleague instanceof Alarm) { interMap.put(“Alarm”, colleagueName); } else if (colleague instanceof CoffeeMachine) { interMap.put(“CoffeeMachine”, colleagueName); } else if (colleague instanceof TV) { interMap.put(“TV”, colleagueName); } else if (colleague instanceof Curtains) { interMap.put(“Curtains”, colleagueName); } } //具体中介者的核心方法 |
---|
//1. 根据得到消息,完成对应任务 //2. 中介者在这个方法,协调各个具体的同事对象,完成任务 @Override public void GetMessage(int stateChange, String colleagueName) { // TODO Auto-generated method stub //处理闹钟发出的消息 if (colleagueMap.get(colleagueName) instanceof Alarm) { if (stateChange == 0) { ((CoffeeMachine) (colleagueMap.get(interMap .get(“CoffeeMachine”)))).StartCoffee(); ((TV) (colleagueMap.get(interMap.get(“TV”)))).StartTv(); } else if (stateChange == 1) { ((TV) (colleagueMap.get(interMap.get(“TV”)))).StopTv(); } } else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) { ((Curtains) (colleagueMap.get(interMap.get(“Curtains”)))) .UpCurtains(); } else if (colleagueMap.get(colleagueName) instanceof TV) {//如果 TV 发现消息 } else if (colleagueMap.get(colleagueName) instanceof Curtains) { //如果是以窗帘发出的消息,这里处理… } |
---|
} @Override public void SendMessage() { // TODO Auto-generated method stub } } |
---|
package com.atguigu.mediator.smarthouse; public class Curtains extends Colleague { public Curtains(Mediator mediator, String name) { super(mediator, name); // TODO Auto-generated constructor stub mediator.Register(name, this); } @Override public void SendMessage(int stateChange) { // TODO Auto-generated method stub this.GetMediator().GetMessage(stateChange, this.name); } |
public void UpCurtains() { System.out.println(“I am holding Up Curtains!”); } } |
---|
package com.atguigu.mediator.smarthouse; public abstract class Mediator { //将给中介者对象,加入到集合中 public abstract void Register(String colleagueName, Colleague colleague); //接收消息, 具体的同事对象发出 public abstract void GetMessage(int stateChange, String colleagueName); public abstract void SendMessage(); } |
package com.atguigu.mediator.smarthouse; public class TV extends Colleague { public TV(Mediator mediator, String name) { super(mediator, name); // TODO Auto-generated constructor stub mediator.Register(name, this); |
} @Override public void SendMessage(int stateChange) { // TODO Auto-generated method stub this.GetMediator().GetMessage(stateChange, this.name); } public void StartTv() { // TODO Auto-generated method stub System.out.println(“It’s time to StartTv!”); } public void StopTv() { // TODO Auto-generated method stub System.out.println(“StopTv!”); } } |
---|
游戏角色有攻击力和防御力,在大战Boss 前保存自身的状态(攻击力和防御力),当大战 Boss 后攻击力和防御力下降,从备忘录对象恢复到大战前的状态
传统的方式的问题分析
一个对象,就对应一个保存对象状态的对象, 这样当我们游戏的对象很多时,不利于管理,开销也很大.
传统的方式是简单地做备份,new 出另外一个对象出来,再把需要备份的数据放到这个新对象,但这就暴露了对象内部的细节
解决方案: => 备忘录模式
基本介绍
备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
可以这里理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意见的事情,以防忘记了。而在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作
备忘录模式属于行为型模式
theory.zip
package com.atguigu.memento.theory; |
---|
import java.util.ArrayList; import java.util.List; public class Caretaker { //在 List 集合中会有很多的备忘录对象 private List mementoList = new ArrayList(); public void add(Memento memento) { mementoList.add(memento); } //获取到第 index 个 Originator 的 备忘录对象(即保存状态) public Memento get(int index) { return mementoList.get(index); } } |
---|
package com.atguigu.memento.theory; import java.util.ArrayList; import java.util.HashMap; public class Client { |
public static void main(String[] args) { // TODO Auto-generated method stub Originator originator = new Originator(); Caretaker caretaker = new Caretaker(); originator.setState(" 状态#1 攻击力 100 “); //保存了当前的状态caretaker.add(originator.saveStateMemento()); originator.setState(” 状态#2 攻击力 80 “); caretaker.add(originator.saveStateMemento()); originator.setState(” 状态#3 攻击力 50 "); caretaker.add(originator.saveStateMemento()); System.out.println(“当前的状态是 =” + originator.getState()); //希望得到状态 1, 将 originator 恢复到状态 1 originator.getStateFromMemento(caretaker.get(0)); System.out.println(“恢复到状态 1 , 当前的状态是”); |
---|
System.out.println(“当前的状态是 =” + originator.getState()); } } |
---|
package com.atguigu.memento.theory; public class Memento { private String state; //构造器 public Memento(String state) { super(); this.state = state; } public String getState() { return state; } } |
package com.atguigu.memento.theory; public class Originator { private String state;//状态信息 public String getState() { return state; } public void setState(String state) { this.state = state; } //编写一个方法,可以保存一个状态对象 Memento //因此编写一个方法,返回 Memento public Memento saveStateMemento() { return new Memento(state); } //通过备忘录对象,恢复状态 public void getStateFromMemento(Memento memento) { state = memento.getState(); } } |
游戏角色有攻击力和防御力,在大战 Boss 前保存自身的状态(攻击力和防御力),当大战 Boss 后攻击力和防御力下降,从备忘录对象恢复到大战前的状态
game.zip
package com.atguigu.memento.game; import java.util.ArrayList; import java.util.HashMap; |
---|
//守护者对象, 保存游戏角色的状态 public class Caretaker { //如果只保存一次状态private Memento memento; //对 GameRole 保存多次状态 //private ArrayList mementos; //对多个游戏角色保存多个状态 //private HashMap public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } |
---|
package com.atguigu.memento.game; public class Client { public static void main(String[] args) { |
// TODO Auto-generated method stub //创建游戏角色 GameRole gameRole = new GameRole(); gameRole.setVit(100); gameRole.setDef(100); System.out.println(“和 boss 大战前的状态”); gameRole.display(); //把当前状态保存 caretaker Caretaker caretaker = new Caretaker(); caretaker.setMemento(gameRole.createMemento()); System.out.println(“和 boss 大战~~~”); gameRole.setDef(30); gameRole.setVit(30); gameRole.display(); System.out.println(“大战后,使用备忘录对象恢复到站前”); gameRole.recoverGameRoleFromMemento(caretaker.getMemento()); System.out.println(“恢复后的状态”); gameRole.display(); } |
---|
} |
---|
package com.atguigu.memento.game; public class GameRole { private int vit; private int def; //创建 Memento ,即根据当前的状态得到 Memento public Memento createMemento() { return new Memento(vit, def); } //从备忘录对象,恢复 GameRole 的状态 public void recoverGameRoleFromMemento(Memento memento) { this.vit = memento.getVit(); this.def = memento.getDef(); } //显示当前游戏角色的状态public void display() { System.out.println(“游戏角色当前的攻击力:” + this.vit + " 防御力: " + this.def); } public int getVit() { |
return vit; } public void setVit(int vit) { this.vit = vit; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } } |
---|
package com.atguigu.memento.game; public class Memento { //攻击力private int vit; //防御力 private int def; |
public Memento(int vit, int def) { super(); this.vit = vit; this.def = def; } public int getVit() { return vit; } public void setVit(int vit) { this.vit = vit; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } } |
---|
通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求
基本介绍
-应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
-一些重复出现的问题可以用一种简单的语言来表达
-一个简单语法需要解释的场景
通过解释器模式来实现四则运算, 如计算 a+b-c 的值
interpreter.zip
| package com.atguigu.interpreter;
import java.util.HashMap;
/**
- 加法解释器
- @author Administrator
/ public class AddExpression extends SymbolExpression { |
---|
public AddExpression(Expression left, Expression right) { super(left, right); } //处理相加 //var 仍然是 {a=10,b=20}… //一会我们 debug 源码,就 ok public int interpreter(HashMap //super.left.interpreter(var) : 返回 left 表达式对应的值 a = 10 //super.right.interpreter(var): 返回 right 表达式对应值 b = 20 return super.left.interpreter(var) + super.right.interpreter(var); } } |
---|
package com.atguigu.interpreter; import java.util.HashMap; import java.util.Stack; public class Calculator { // 定义表达式 private Expression expression; // 构造函数传参,并解析 |
public Calculator(String expStr) { // expStr = a+b // 安排运算先后顺序 Stack stack = new Stack<>(); // 表达式拆分成字符数组 char[] charArray = expStr.toCharArray();// [a, +, b] Expression left = null; Expression right = null; //遍历我们的字符数组, 即遍历 [a, +, b] //针对不同的情况,做处理 for (int i = 0; i < charArray.length; i++) { switch (charArray[i]) { case ‘+’: // left = stack.pop();// 从 stack 取出 left => “a” right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表达式 “b” stack.push(new AddExpression(left, right));// 然后根据得到 left 和 right 构建 AddExpresson 加入 stack break; case ‘-’: // left = stack.pop(); right = new VarExpression(String.valueOf(charArray[++i])); stack.push(new SubExpression(left, right)); break; default: //如果是一个 Var 就创建要给 VarExpression 对象,并 push 到 stack stack.push(new VarExpression(String.valueOf(charArray[i]))); |
---|
break; } } //当遍历完整个 charArray 数组后,stack 就得到最后 Expression this.expression = stack.pop(); } public int run(HashMap //最后将表达式 a+b 和 var = {a=10,b=20} //然后传递给 expression 的 interpreter 进行解释执行 return this.expression.interpreter(var); } } |
---|
package com.atguigu.interpreter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; public class ClientTest { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub String expStr = getExpStr(); // a+b HashMap |
Calculator calculator = new Calculator(expStr); System.out.println(“运算结果:” + expStr + “=” + calculator.run(var)); } // 获得表达式 public static String getExpStr() throws IOException { System.out.print(“请输入表达式:”); return (new BufferedReader(new InputStreamReader(System.in))).readLine(); } // 获得值映射 public static HashMap for (char ch : expStr.toCharArray()) { if (ch != ‘+’ && ch != ‘-’) { if (!map.containsKey(String.valueOf(ch))) { System.out.print(“请输入” + String.valueOf(ch) + “的值:”); String in = (new BufferedReader(new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch), Integer.valueOf(in)); } } } return map; } |
---|
} |
---|
package com.atguigu.interpreter; import java.util.HashMap; /** - 抽象类表达式,通过 HashMap 键值对, 可以获取到变量的值 |
* - @author Administrator |
/ public abstract class Expression { // a + b - c // 解释公式和数值, key 就是公式(表达式) 参数[a,b,c], value 就是就是具体值 // HashMap {a=10, b=20} public abstract int interpreter(HashMap } |
package com.atguigu.interpreter; import java.util.HashMap; public class SubExpression extends SymbolExpression { public SubExpression(Expression left, Expression right) { |
super(left, right); } //求出 left 和 right 表达式相减后的结果 public int interpreter(HashMap return super.left.interpreter(var) - super.right.interpreter(var); } } |
---|
package com.atguigu.interpreter; import java.util.HashMap; /** - 抽象运算符号解析器 这里,每个运算符号,都只和自己左右两个数字有关系, - 但左右两个数字有可能也是一个解析的结果,无论何种类型,都是 Expression 类的实现类 |
* - @author Administrator |
/ public class SymbolExpression extends Expression { protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { |
this.left = left; this.right = right; } //因为 SymbolExpression 是让其子类来实现,因此 interpreter 是一个默认实现 @Override public int interpreter(HashMap // TODO Auto-generated method stub return 0; } } |
---|
package com.atguigu.interpreter; import java.util.HashMap; /** - 变量的解释器 - @author Administrator |
/ public class VarExpression extends Expression { private String key; // key=a,key=b,key=c |
public VarExpression(String key) { this.key = key; } // var 就是{a=10, b=20} // interpreter 根据 变量名称,返回对应值 @Override public int interpreter(HashMap } } |
---|
请编写程序完成 APP 抽奖活动 具体要求如下:
基本介绍
完成 APP 抽奖活动项目,使用状态模式.
-定义出一个接口叫状态接口,每个状态都实现它。
-接口有扣除积分方法、抽奖方法、发放奖品方法
state.zip
| package com.atguigu.state;
import java.util.Random;
/**
- 可以抽奖的状态
- @author Administrator
/ public class CanRaffleState extends State { RaffleActivity activity; public CanRaffleState(RaffleActivity activity) { this.activity = activity; } //已经扣除了积分,不能再扣@Override public void deductMoney() { System.out.println(“已经扣取过了积分”); } |
---|
//可以抽奖, 抽完奖后,根据实际情况,改成新的状态 @Override public boolean raffle() { System.out.println(“正在抽奖,请稍等!”); Random r = new Random(); int num = r.nextInt(10); // 10%中奖机会if(num == 0){ // 改变活动状态为发放奖品 context activity.setState(activity.getDispenseState()); return true; }else{ System.out.println(“很遗憾没有抽中奖品!”); // 改变状态为不能抽奖activity.setState(activity.getNoRafflleState()); return false; } } // 不能发放奖品 @Override public void dispensePrize() { System.out.println(“没中奖,不能发放奖品”); } } |
---|
| package com.atguigu.state;
/**
- 状态模式测试类
- @author Administrator
/ public class ClientTest { public static void main(String[] args) { // TODO Auto-generated method stub // 创建活动对象,奖品有 1 个奖品 RaffleActivity activity = new RaffleActivity(1); // 我们连续抽 300 次奖 for (int i = 0; i < 30; i++) { System.out.println(“--------第” + (i + 1) + "次抽奖 "); // 参加抽奖,第一步点击扣除积分 activity.debuctMoney(); // 第二步抽奖 activity.raffle(); } } } |
---|
package com.atguigu.state; /** - 奖品发放完毕状态 - 说明,当我们 activity 改变成 DispenseOutState, 抽奖活动结束 - @author Administrator |
/ public class DispenseOutState extends State { // 初始化时传入活动引用 RaffleActivity activity; public DispenseOutState(RaffleActivity activity) { this.activity = activity; } @Override public void deductMoney() { System.out.println(“奖品发送完了,请下次再参加”); } @Override public boolean raffle() { System.out.println(“奖品发送完了,请下次再参加”); return false; |
} @Override public void dispensePrize() { System.out.println(“奖品发送完了,请下次再参加”); } } |
---|
package com.atguigu.state; /** - 发放奖品的状态 - @author Administrator |
/ public class DispenseState extends State { // 初始化时传入活动引用,发放奖品后改变其状态 RaffleActivity activity; public DispenseState(RaffleActivity activity) { this.activity = activity; } // |
@Override public void deductMoney() { System.out.println(“不能扣除积分”); } @Override public boolean raffle() { System.out.println(“不能抽奖”); return false; } //发放奖品@Override public void dispensePrize() { if(activity.getCount() > 0){ System.out.println(“恭喜中奖了”); // 改变状态为不能抽奖 activity.setState(activity.getNoRafflleState()); }else{ System.out.println(“很遗憾,奖品发送完了”); // 改变状态为奖品发送完毕, 后面我们就不可以抽奖 activity.setState(activity.getDispensOutState()); //System.out.println(“抽奖活动结束”); //System.exit(0); } |
---|
} } |
---|
package com.atguigu.state; /** - 不能抽奖状态 - @author Administrator |
/ public class NoRaffleState extends State { // 初始化时传入活动引用,扣除积分后改变其状态 RaffleActivity activity; public NoRaffleState(RaffleActivity activity) { this.activity = activity; } // 当前状态可以扣积分 , 扣除后,将状态设置成可以抽奖状态 @Override public void deductMoney() { System.out.println(“扣除 50 积分成功,您可以抽奖了”); activity.setState(activity.getCanRaffleState()); } |
// 当前状态不能抽奖 | |
---|---|
@Override | |
public boolean raffle() { | |
System.out.println(“扣了积分才能抽奖喔!”); | |
return false; | |
} | |
// 当前状态不能发奖品 |
|
@Override | |
public void dispensePrize() { | |
System.out.println(“不能发放奖品”); | |
} | |
} | |
package com.atguigu.state; | |
/** |
|
* 抽奖活动 // | |
* | |
* @author Administrator | |
* | |
*/ | |
public class RaffleActivity { | |
// state 表示活动当前的状态,是变化 |
|
State state = null; |
// 奖品数量 int count = 0; // 四个属性,表示四种状态 State noRafflleState = new NoRaffleState(this); State canRaffleState = new CanRaffleState(this); State dispenseState = new DispenseState(this); State dispensOutState = new DispenseOutState(this); //构造器 //1. 初始化当前的状态为 noRafflleState(即不能抽奖的状态) //2. 初始化奖品的数量 public RaffleActivity( int count) { this.state = getNoRafflleState(); this.count = count; } //扣分, 调用当前状态的 deductMoney public void debuctMoney(){ state.deductMoney(); } //抽奖 public void raffle(){ // 如果当前的状态是抽奖成功 |
---|
if(state.raffle()){ //领取奖品state.dispensePrize(); } } public State getState() { return state; } public void setState(State state) { this.state = state; } //这里请大家注意,每领取一次奖品,count-- public int getCount() { int curCount = count; count–; return curCount; } public void setCount(int count) { this.count = count; } |
---|
public State getNoRafflleState() { return noRafflleState; } public void setNoRafflleState(State noRafflleState) { this.noRafflleState = noRafflleState; } public State getCanRaffleState() { return canRaffleState; } public void setCanRaffleState(State canRaffleState) { this.canRaffleState = canRaffleState; } public State getDispenseState() { return dispenseState; } public void setDispenseState(State dispenseState) { this.dispenseState = dispenseState; } public State getDispensOutState() { return dispensOutState; |
---|
} public void setDispensOutState(State dispensOutState) { this.dispensOutState = dispensOutState; } } |
---|
package com.atguigu.state; /** - 状态抽象类 - @author Administrator |
/ public abstract class State { // 扣除积分 - 50 public abstract void deductMoney(); // 是否抽中奖品 public abstract boolean raffle(); // 发放奖品 public abstract void dispensePrize(); |
} |
---|
money.zip
package com.atguigu.state.money; public abstract class AbstractState implements State { protected static final RuntimeException EXCEPTION = new RuntimeException(“操作流程不允许”); //抽象类,默认实现了 State 接口的所有方法 //该类的所有方法,其子类(具体的状态类),可以有选择的进行重写 |
---|
@Override public void checkEvent(Context context) { throw EXCEPTION; } @Override public void checkFailEvent(Context context) { throw EXCEPTION; } @Override public void makePriceEvent(Context context) { throw EXCEPTION; } @Override public void acceptOrderEvent(Context context) { throw EXCEPTION; } @Override public void notPeopleAcceptEvent(Context context) { throw EXCEPTION; } @Override |
---|
public void payOrderEvent(Context context) { throw EXCEPTION; } @Override public void orderFailureEvent(Context context) { throw EXCEPTION; } @Override public void feedBackEvent(Context context) { throw EXCEPTION; } } |
---|
package com.atguigu.state.money; //各种具体状态类 class FeedBackState extends AbstractState { @Override public String getCurrentState() { return StateEnum.FEED_BACKED.getValue(); } } |
class GenerateState extends AbstractState { @Override public void checkEvent(Context context) { context.setState(new ReviewState()); } @Override public void checkFailEvent(Context context) { context.setState(new FeedBackState()); } @Override public String getCurrentState() { return StateEnum.GENERATE.getValue(); } } class NotPayState extends AbstractState { @Override public void payOrderEvent(Context context) { context.setState(new PaidState()); } @Override |
---|
public void feedBackEvent(Context context) { context.setState(new FeedBackState()); } @Override public String getCurrentState() { return StateEnum.NOT_PAY.getValue(); } } class PaidState extends AbstractState { @Override public void feedBackEvent(Context context) { context.setState(new FeedBackState()); } @Override public String getCurrentState() { return StateEnum.PAID.getValue(); } } class PublishState extends AbstractState { @Override |
---|
public void acceptOrderEvent(Context context) { //把当前状态设置为 NotPayState。。。 //至于应该变成哪个状态,有流程图来决定context.setState(new NotPayState()); } @Override public void notPeopleAcceptEvent(Context context) { context.setState(new FeedBackState()); } @Override public String getCurrentState() { return StateEnum.PUBLISHED.getValue(); } } class ReviewState extends AbstractState { @Override public void makePriceEvent(Context context) { context.setState(new PublishState()); } @Override public String getCurrentState() { |
---|
return StateEnum.REVIEWED.getValue(); } } |
---|
package com.atguigu.state.money; /*测试类/ public class ClientTest { public static void main(String[] args) { // TODO Auto-generated method stub //创建 context 对象 Context context = new Context(); //将当前状态设置为 PublishState context.setState(new PublishState()); System.out.println(context.getCurrentState()); // //publish --> not pay context.acceptOrderEvent(context); // //not pay --> paid context.payOrderEvent(context); // // 失败, 检测失败时,会抛出异常 // try { // context.checkFailEvent(context); // System.out.println(“流程正常…”); // } catch (Exception e) { |
// // TODO: handle exception // System.out.println(e.getMessage()); // } } } |
---|
package com.atguigu.state.money; //环境上下文 public class Context extends AbstractState{ //当前的状态 state, 根据我们的业务流程处理,不停的变化 private State state; @Override public void checkEvent(Context context) { state.checkEvent(this); getCurrentState(); } @Override public void checkFailEvent(Context context) { state.checkFailEvent(this); getCurrentState(); } |
@Override public void makePriceEvent(Context context) { state.makePriceEvent(this); getCurrentState(); } @Override public void acceptOrderEvent(Context context) { state.acceptOrderEvent(this); getCurrentState(); } @Override public void notPeopleAcceptEvent(Context context) { state.notPeopleAcceptEvent(this); getCurrentState(); } @Override public void payOrderEvent(Context context) { state.payOrderEvent(this); getCurrentState(); } @Override |
---|
public void orderFailureEvent(Context context) { state.orderFailureEvent(this); getCurrentState(); } @Override public void feedBackEvent(Context context) { state.feedBackEvent(this); getCurrentState(); } public State getState() { return state; } public void setState(State state) { this.state = state; } @Override public String getCurrentState() { System.out.println("当前状态 : " + state.getCurrentState()); return state.getCurrentState(); } } |
---|
| package com.atguigu.state.money;
/
- 状态接口
- @author Administrator
/
public interface State {
/
- 电审
*/
void checkEvent(Context context);
/
- 电审失败
*/
void checkFailEvent(Context context);
/
- 定价发布
*/ void makePriceEvent(Context context); /** - 接单 |
---|
| */
void acceptOrderEvent(Context context);
/
- 无人接单失效
*/
void notPeopleAcceptEvent(Context context);
/
- 付款
*/
void payOrderEvent(Context context);
/
- 接单有人支付失效
*/
void orderFailureEvent(Context context);
/
- 反馈
*/ void feedBackEvent(Context context); String getCurrentState(); } |
---|
package com.atguigu.state.money; /** - 状态枚举类 - @author Administrator |
/ public enum StateEnum { //订单生成 GENERATE(1, “GENERATE”), //已审核 REVIEWED(2, “REVIEWED”), //已发布 PUBLISHED(3, “PUBLISHED”), //待付款 NOT_PAY(4, “NOT_PAY”), //已付款 PAID(5, “PAID”), //已完结 |
FEED_BACKED(6, “FEED_BACKED”); private int key; private String value; StateEnum(int key, String value) { this.key = key; this.value = value; } public int getKey() {return key;} public String getValue() {return value;} } |
---|
strategy.zip
package com.atguigu.strategy; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //测试 } } |
---|
package com.atguigu.strategy; public abstract class Duck { public Duck() { } public abstract void display();//显示鸭子信息 public void quack() { System.out.println(“鸭子嘎嘎叫~~”); } public void swim() { System.out.println(“鸭子会游泳~~”); } public void fly() { System.out.println(“鸭子会飞翔~~~”); } } |
package com.atguigu.strategy; |
public class PekingDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println(“ } //因为北京鸭不能飞翔,因此需要重写 fly @Override public void fly() { // TODO Auto-generated method stub System.out.println(“北京鸭不能飞翔”); } } |
---|
package com.atguigu.strategy; public class ToyDuck extends Duck{ @Override public void display() { // TODO Auto-generated method stub System.out.println(“玩具鸭”); |
} //需要重写父类的所有方法 public void quack() { System.out.println(“玩具鸭不能叫~~”); } public void swim() { System.out.println(“玩具鸭不会游泳~~”); } public void fly() { System.out.println(“玩具鸭不会飞翔~~~”); } } |
---|
package com.atguigu.strategy; public class WildDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println(" 这是野鸭 "); } |
} |
---|
说明:从上图可以看到,客户 context 有成员变量 strategy 或者其他的策略接口
,至于需要使用到哪个策略,我们可以在构造器中指定
编写程序完成前面的鸭子项目,要求使用策略模式
策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是: 分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者
improve.zip
package com.atguigu.strategy.improve; public class BadFlyBehavior implements FlyBehavior { |
---|
@Override public void fly() { // TODO Auto-generated method stub System.out.println(" 飞翔技术一般 "); } } |
---|
package com.atguigu.strategy.improve; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub WildDuck wildDuck = new WildDuck(); wildDuck.fly();// ToyDuck toyDuck = new ToyDuck(); toyDuck.fly(); PekingDuck pekingDuck = new PekingDuck(); pekingDuck.fly(); //动态改变某个对象的行为, 北京鸭 不能飞 pekingDuck.setFlyBehavior(new NoFlyBehavior()); System.out.println(“北京鸭的实际飞翔能力”); |
pekingDuck.fly(); } } |
---|
package com.atguigu.strategy.improve; public abstract class Duck { //属性, 策略接口 FlyBehavior flyBehavior; //其它属性<->策略接口QuackBehavior quackBehavior; public Duck() { } public abstract void display();//显示鸭子信息 public void quack() { System.out.println(“鸭子嘎嘎叫~~”); } public void swim() { System.out.println(“鸭子会游泳~~”); |
} | |
---|---|
public void fly() { |
|
//改进 |
|
if(flyBehavior != null) { | |
flyBehavior.fly(); | |
} | |
} | |
public void setFlyBehavior(FlyBehavior flyBehavior) { |
|
this.flyBehavior = flyBehavior; | |
} | |
public void setQuackBehavior(QuackBehavior quackBehavior) { |
|
this.quackBehavior = quackBehavior; | |
} | |
} |
|
package com.atguigu.strategy.improve; public interface FlyBehavior { |
void fly(); // 子类具体实现 } |
---|
package com.atguigu.strategy.improve; public class GoodFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println(" 飞翔技术高超 ~~~"); } } |
package com.atguigu.strategy.improve; public class NoFlyBehavior implements FlyBehavior{ @Override public void fly() { // TODO Auto-generated method stub System.out.println(" 不会飞翔 "); } |
} |
---|
package com.atguigu.strategy.improve; public class PekingDuck extends Duck { //假如北京鸭可以飞翔,但是飞翔技术一般public PekingDuck() { // TODO Auto-generated constructor stub flyBehavior = new BadFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println(“ } } |
package com.atguigu.strategy.improve; |
public interface QuackBehavior { void quack();//子类实现 } |
---|
package com.atguigu.strategy.improve; public class ToyDuck extends Duck{ public ToyDuck() { // TODO Auto-generated constructor stub flyBehavior = new NoFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println(“玩具鸭”); } //需要重写父类的所有方法 public void quack() { System.out.println(“玩具鸭不能叫~~”); } |
public void swim() { System.out.println(“玩具鸭不会游泳~~”); } } |
---|
package com.atguigu.strategy.improve; public class WildDuck extends Duck { //构造器,传入 FlyBehavor 的对象 public WildDuck() { // TODO Auto-generated constructor stub flyBehavior = new GoodFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println(" 这是野鸭 "); } } |
package com.atguigu.jdk; import java.util.Arrays; import java.util.Comparator; public class Strategy { public static void main(String[] args) { |
---|
// TODO Auto-generated method stub //数组 Integer[] data = { 9, 1, 2, 8, 4, 3 }; // 实现降序排序,返回-1 放左边,1 放右边,0 保持不变 // 说明 // 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator(){…} // 2. 对象 new Comparator(){…} 就是实现了 策略接口 的对象 // 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式 Comparator comparator = new Comparator() { public int compare(Integer o1, Integer o2) { if (o1 > o2) { return -1; } else { return 1; } }; }; // 说明 / public static void sort(T[] a, Comparator super T> c) { if (c == null) { sort(a); //默认方法 } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); //使用策略对象 c |
---|
else // 使用策略对象 c TimSort.sort(a, 0, a.length, c, null, 0, 0); } } */ //方式 1 Arrays.sort(data, comparator); System.out.println(Arrays.toString(data)); // 降序排序 //方式 2- 同时 lambda 表达式实现 策略模式 Integer[] data2 = { 19, 11, 12, 18, 14, 13 }; Arrays.sort(data2, (var1, var2) -> { if(var1.compareTo(var2) > 0) { return -1; } else { return 1; } }); System.out.println(“data2=” + Arrays.toString(data2)); } |
---|
} |
---|
采购员采购教学器材
1) 如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000)
2) 如果金额 小于等于 10000, 由院长审批 (5000
基本介绍
编写程序完成学校 OA 系统的采购审批项目:需求采购员采购教学器材
如果金额 小于等于 5000, 由教学主任审批如果金额 小于等于 10000, 由院长审批
如果金额 小于等于 30000, 由副校长审批如果金额 超过 30000 以上,有校长审批
responsibilitychain.zip
package com.atguigu.responsibilitychain; public abstract class Approver { |
---|
Approver approver; //下一个处理者String name; // 名字 public Approver(String name) { // TODO Auto-generated constructor stub this.name = name; } //下一个处理者 public void setApprover(Approver approver) { this.approver = approver; } //处理审批请求的方法,得到一个请求, 处理是子类完成,因此该方法做成抽象 public abstract void processRequest(PurchaseRequest purchaseRequest); } |
---|
package com.atguigu.responsibilitychain; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建一个请求 PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1); |
//创建相关的审批人 DepartmentApprover departmentApprover = new DepartmentApprover(“张主任”); CollegeApprover collegeApprover = new CollegeApprover(“李院长”); ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover(“王副校”); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover(“佟校长”); //需要将各个审批级别的下一个设置好 (处理人构成环形: ) departmentApprover.setApprover(collegeApprover); collegeApprover.setApprover(viceSchoolMasterApprover); viceSchoolMasterApprover.setApprover(schoolMasterApprover); schoolMasterApprover.setApprover(departmentApprover); departmentApprover.processRequest(purchaseRequest); viceSchoolMasterApprover.processRequest(purchaseRequest); } } |
---|
package com.atguigu.responsibilitychain; public class CollegeApprover extends Approver { |
public CollegeApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) { System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理"); }else { approver.processRequest(purchaseRequest); } } } |
---|
package com.atguigu.responsibilitychain; public class DepartmentApprover extends Approver { public DepartmentApprover(String name) { // TODO Auto-generated constructor stub super(name); } |
@Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() <= 5000) { System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理"); }else { approver.processRequest(purchaseRequest); } } } |
---|
package com.atguigu.responsibilitychain; //请求类 public class PurchaseRequest { private int type = 0; //请求类型private float price = 0.0f; //请求金额private int id = 0; //构造器 public PurchaseRequest(int type, float price, int id) { this.type = type; this.price = price; this.id = id; |
} public int getType() { return type; } public float getPrice() { return price; } public int getId() { return id; } } |
---|
package com.atguigu.responsibilitychain; public class SchoolMasterApprover extends Approver { public SchoolMasterApprover(String name) { // TODO Auto-generated constructor stub super(name); } |
@Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() > 30000) { System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理"); }else { approver.processRequest(purchaseRequest); } } } |
---|
package com.atguigu.responsibilitychain; public class ViceSchoolMasterApprover extends Approver { public ViceSchoolMasterApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) { System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理"); }else { |
approver.processRequest(purchaseRequest); } } } |
---|
package com.atguigu.spring.test; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerInterceptor; public class ResponsibilityChain { |
---|
|
public static void main(String[] args) {
// TODO Auto-generated method stub
// DispatcherServlet
//说明
/
- protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
- HandlerExecutionChain mappedHandler = null;
- mappedHandler = getHandler(processedRequest);//获取到 HandlerExecutionChain 对象
- //在 mappedHandler.applyPreHandle 内部 得到啦 HandlerInterceptor interceptor
- //调用了拦截器的 interceptor.preHandle
- if (!mappedHandler.applyPreHandle(processedRequest, response)) { return;
} //说明:mappedHandler.applyPostHandle 方法内部获取到拦截器,并调用 //拦截器的 interceptor.postHandle(request, response, this.handler, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); * } - //说明:在 mappedHandler.applyPreHandle 内部中, - 还调用了 triggerAfterCompletion 方法,该方法中调用了 |
---|
* HandlerInterceptor interceptor = getInterceptors()[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error(“HandlerInterceptor.afterCompletion threw exception”, ex2); } */ } } |
---|
对 Encoding 的处理、拦截器