设计原理上
Java设计模式
1 前言
1.1 目的
2 七大原则
2.1 单一职责原则
方案一
package com.feng.principle.singleresponsibility;
/**
* @Author feng peng
* @Date 2023/4/12
* @Time 22:53
*/
public class singleResponsibility01 {
public static void main(String[] args) {
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 + " 在公路上运行...");
}
}
方案二
package com.feng.principle.singleresponsibility;
/**
* @Author feng peng
* @Date 2023/4/12
* @Time 22:53
*/
public class singleResponsibility02 {
public static void main(String[] args) {
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.feng.principle.singleresponsibility;
/**
* @Author feng peng
* @Date 2023/4/12
* @Time 22:53
*/
public class singleResponsibility03 {
public static void main(String[] args) {
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.2 接口隔离原则
package com.feng.principle.segregation;
/**
* @Author feng peng
* @Date 2023/4/23
* @Time 21:28
*/
public class Segregation01 {
public static void main(String[] args) {
}
}
interface Interface1{
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
class B implements Interface1{
@Override
public void operation1() {
System.out.println("B 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("B 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("B 实现了 operation3");
}
@Override
public void operation4() {
System.out.println("B 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("B 实现了 operation5");
}
}
class D implements Interface1{
@Override
public void operation1() {
System.out.println("D 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("D 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("D 实现了 operation3");
}
@Override
public void operation4() {
System.out.println("D 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("D 实现了 operation5");
}
}
class A { //A 类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i){
i.operation1();
}
public void depend2(Interface1 i){
i.operation2();
}
public void depend3(Interface1 i){
i.operation3();
}
}
class C { // C类通过接口Interface1 依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i){
i.operation1();
}
public void depend4(Interface1 i){
i.operation4();
}
public void depend5(Interface1 i){
i.operation5();
}
}
package com.feng.principle.segregation.improve;
/**
* @Author feng peng
* @Date 2023/4/23
* @Time 21:28
*/
public class Segregation02 {
public static void main(String[] args) {
// 使用一把
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());
}
}
interface Interface1{
void operation1();
}
//接口2
interface Interface2{
void operation2();
void operation3();
}
//接口3
interface Interface3{
void operation4();
void operation5();
}
class B implements Interface1,Interface2{
@Override
public void operation1() {
System.out.println("B 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("B 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("B 实现了 operation3");
}
}
class D implements Interface1,Interface3{
@Override
public void operation1() {
System.out.println("D 实现了 operation1");
}
@Override
public void operation4() {
System.out.println("D 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("D 实现了 operation5");
}
}
class A { //A 类通过接口Interface1,Interface2 依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i){
i.operation1();
}
public void depend2(Interface2 i){
i.operation2();
}
public void depend3(Interface2 i){
i.operation3();
}
}
class C { // C类通过接口Interface1,Interface3 依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i){
i.operation1();
}
public void depend4(Interface3 i){
i.operation4();
}
public void depend5(Interface3 i){
i.operation5();
}
}
运行结果
2.3 依赖倒转原则
实现方案1代码
package com.feng.principle.inversion;
public class DependecyInversion {
public static void main(String[] args) {
Persion persion = new Persion();
persion.receive(new Email());
}
}
class Email{
public String getInfo(){
return "电子邮件信息:hello,world";
}
}
//完成Person接收消息的功能
//方式1分析
// 1.简单,比较容易想到
// 2.如果我们获取的对象是 微信,短信等等,则新增类,同时Person也要增加相应的接收方法
// 3.解决思路:引入一个抽象的接口IReceiver, 表示接收者,这样Person类与接口IReceiver发生依赖
// 因为Email,WeChat 等等属于接收的范围,他们各自实现IReceiver 接口就OK,这样我们就符合依赖倒转原则
class Persion{
public void receive(Email email){
System.out.println(email.getInfo());
}
}
实现方案2改进代码
package com.feng.principle.inversion.improve;
public class DependecyInversion {
public static void main(String[] args) {
//客户端无需改变
Persion persion = new Persion();
persion.receive(new Email());
persion.receive(new WeChat());
}
}
//定义接口
interface IReceiver{
public String getInfo();
}
class Email implements IReceiver{
public String getInfo(){
return "电子邮件信息:hello,world";
}
}
//增加微信
class WeChat implements IReceiver{
@Override
public String getInfo() {
return "微信消息:hello,ok";
}
}
//方式2
class Persion{
//这里我们是对接口的依赖
public void receive(IReceiver receiver){
System.out.println(receiver.getInfo());
}
}
运行结果
代码实现
package com.feng.principle.inversion.improve;
public class ThreeMethod {
}
// 方式1:通过接口传递实现依赖
// 开关的接口
interface IOpenAndClose{
public void open(ITV tv); //抽象方法,接收接口
}
interface ITV{ //ITV接口
public void play();
}
//实现接口
class OpenAndClose implements IOpenAndClose{
@Override
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;
@Override
public void setTv(ITV tv) {
this.tv = tv;
}
@Override
public void open() {
this.tv.play();
}
}
2.4 里氏替换原则
完整代码
package com.feng.principle.liskov;
public class Liskov {
public static void main(String[] args) {
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.feng.principle.liskov.improve;
public class Liskov {
public static void main(String[] args) {
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
}
}
// A类
class A{
// 返回两个数的差
public int func1(int num1,int num2){
return num1 - num2;
}
}
// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends A {
//如果B需要使用A类的方法,使用组合关系
private A a = new A();
//这里,重写了A类的方法,可能是无意识
public int func1(int a,int b){
return a+b;
}
public int func2(int a,int b){
return func1(a,b)+9;
}
//我们仍然想使用A的方法
public int func3(int a,int b){
return this.a.func1(a,b);
}
}
运行结果
2.5 开闭原则
案例一
package com.feng.principle.ocp;
public class Ocp {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
}
}
//这是一个用于绘图的类
class GraphicEditor{
//接收Shape对象,然后根据type,来绘制不同的图形
public void drawShape(Shape s){
if(s.m_type == 1){
drawRectangle(s);
}else if(s.m_type == 2){
drawCircle(s);
}
}
public void drawRectangle(Shape r){
System.out.println("绘制矩形");
}
public void drawCircle(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;
}
}
运行结果
完整代码
package com.feng.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;
}
}
完整代码
package com.feng.principle.ocp.imporve;
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() {
System.out.println("绘制矩形");
}
}
class Circle extends Shape{
Circle(){
super.m_type = 2;
}
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
//新增画三角形
class Triangle extends Shape{
Triangle(){
super.m_type = 3;
}
@Override
public void draw() {
System.out.println("绘制三角形");
}
}
//新增一个图形
class OtherGraphic extends Shape{
OtherGraphic(){
super.m_type = 4;
}
@Override
public void draw() {
System.out.println("绘制其他图形");
}
}
2.6 迪米特法则
案例代码
package com.feng.principle.demeter;
import java.util.ArrayList;
import java.util.List;
//客户端
public class Demeter01 {
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 String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
//管理学院员工的管理类
class CollegeManager{
public List<CollegeEmployee> getAllEmployee(){
//返回学院的所有员工
List<CollegeEmployee> 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 类的直接朋友类(成员变量,传入参数,返回值 3个位置)有哪些 Employee CollegeManager
//CollegeEmployee 不是直接朋友 而是一个陌生类,这样违背了迪米特法则
class SchoolManager{
//返回学校总部的员工
public List<Employee> getAllEmployee(){
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
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<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("---------------学院员工--------------");
list1.forEach(e ->{
System.out.println(e.getId());
});
//获取到学校总部员工
List<Employee> list2 = this.getAllEmployee();
System.out.println("-------------学校总部员工---------------");
list2.forEach(e -> System.out.println(e.getId()));
}
}
运行结果
改进完整代码
package com.feng.principle.demeter.improve;
import java.util.ArrayList;
import java.util.List;
//客户端
public class Demeter01 {
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 String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
//管理学院员工的管理类
class CollegeManager{
public List<CollegeEmployee> getAllEmployee(){
//返回学院的所有员工
List<CollegeEmployee> 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<CollegeEmployee> list1 = getAllEmployee();
System.out.println("---------------学院员工--------------");
list1.forEach(e ->{
System.out.println(e.getId());
});
}
}
//学校管理类
//分析SchoolManager 类的直接朋友类(成员变量,传入参数,返回值 3个位置)有哪些 Employee CollegeManager
//CollegeEmployee 不是直接朋友 而是一个陌生类,这样违背了迪米特法则
class SchoolManager{
//返回学校总部的员工
public List<Employee> getAllEmployee(){
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学院总部员工id= "+ i);
list.add(emp);
}
return list;
}
//该方法完成输出学校总部和学院员工信息(id)
void printAllEmployee(CollegeManager sub){
//分析问题
//1. 将输出学院的员工方法,封装到CollegeManager
sub.printEmployee();
//获取到学校总部员工
List<Employee> list2 = this.getAllEmployee();
System.out.println("-------------学校总部员工---------------");
list2.forEach(e -> System.out.println(e.getId()));
}
}
运行结果
2.7 合成复用原则
3 UML类图
3.1 基本介绍
3.2 类图
3.3 依赖
3.4 泛化
3.5 实现
3.6 关联
3.7 聚合
3.8 组合
创建了一个人对象,那么头对象也随之创建好了,所以两者不能分开,所以是组合关系。
4 设计模式
4.1 概述
p28
5 代理模式
5.1 定义
5.2 静态代理
定义
代码实现
ITeacherDao接口
package com.feng.proxy.staticproxy;
// 接口
public interface ITeacherDao {
void teach();// 授课的方法
}
TeacherDao
package com.feng.proxy.staticproxy;
public class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("老师授课中。。。。");
}
}
TeacherDaoProxy
package com.feng.proxy.staticproxy;
//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao{
private ITeacherDao target; // 目标对象,通过接口来聚合
// 构造器
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
System.out.println("开始代理。。。。");
target.teach();
System.out.println("提交。。。。。");
}
}
Client
package com.feng.proxy.staticproxy;
public class Client {
public static void main(String[] args) {
//创建目标对象(被代理的对象)
TeacherDao teacherDao = new TeacherDao();
//创建代理对象,同时将被代理对象传递给代理对象
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
//通过代理对象,调用到被代理对象的方法
//即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
teacherDaoProxy.teach();
}
}
运行结果
5.3 动态代理
定义
代码实现
ITeacherDao接口
package com.feng.proxy.dynamic;
//接口
public interface ITeacherDao {
void teach(); // 授课方法
}
TeacherDao
package com.feng.proxy.dynamic;
public class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("老师授课中。。。。");
}
}
ProxyFactory
package com.feng.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 {
System.out.println("JDK代理开始~~");
// 反射机制调用目标对象的方法
Object returnVal = method.invoke(target, args);
System.out.println("JDK代理提交~~");
return returnVal;
}
});
}
}
Client
package com.feng.proxy.dynamic;
public class Client {
public static void main(String[] args) {
//创建目标对象
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();
}
}
运行结果
5.4 Cglib代理
定义
代码实现
TeacherDao
package com.feng.proxy.cglib;
public class TeacherDao {
public void teach(){
System.out.println("老师授课中,我是cglib代理,不需要实现接口");
}
}
ProxyFactory
package com.feng.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
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 o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib代理模式 开始~");
Object returnVal = method.invoke(target, args);
System.out.println("Cglib代理模式 提交~");
return returnVal;
}
}
Client
package com.feng.proxy.cglib;
public class Client {
public static void main(String[] args) {
//创建目标对象
TeacherDao target = new TeacherDao();
//获取到代理对象,并且将目标对象传递给代理对象
TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法,触发intecept 方法,从而实现对目标对象的调用
proxyInstance.teach();
}
}
运行结果
5.5 变体
6 单例模式
6.1 饿汉式静态变量
public class SingletonTest01 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); //true
}
}
//饿汉式(静态变量)
class Singleton{
//1、构造器私有化,外部不能new
private Singleton(){
}
//2.本类内部创建对象实例
private final static Singleton instance = new Singleton();
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
6.2 饿汉式静态代码块
public class SingletonTest02 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); //true
}
}
//饿汉式(静态变量)
class Singleton{
//1、构造器私有化,外部不能new
private Singleton(){
}
//2.本类内部创建对象实例
private static Singleton instance;
static { //在静态代码块中,创建单例对象
instance = new Singleton();
}
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
6.3 懒汉式(线程不安全)
public class SingleTest03 {
public static void main(String[] args) {
System.out.println("懒汉式,线程不安全~");
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); //true
}
}
class Singleton{
private static Singleton instance;
public Singleton() {
}
//提供一个静态的公有方法,当使用到该方法时,才去创建instance
//即懒汉式
public static Singleton getInstance(){
if (Objects.isNull(instance)){
instance = new Singleton();
}
return instance;
}
}
6.4 懒汉式(线程安全,同步方法)
public class SingleTest04 {
public static void main(String[] args) {
System.out.println("懒汉式2,线程安全~");
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); //true
}
}
//懒汉式(线程安全,同步方法)
class Singleton{
private static Singleton instance;
public Singleton() {
}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static synchronized Singleton getInstance(){
if (Objects.isNull(instance)){
instance = new Singleton();
}
return instance;
}
}
6.5 懒汉式(线程安全,同步代码块)
6.6 双重检查
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
}
}
//懒汉式(线程安全,同步方法)
class Singleton{
private static volatile Singleton instance; //volatile : 变量值一有修改,立即刷到主存中去
public Singleton() {
}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
//同时保证了效率,推荐使用
public static Singleton getInstance(){
if (Objects.isNull(instance)){
synchronized (Singleton.class){
if(Objects.isNull(instance)){
instance = new Singleton();
}
}
}
return instance;
}
}
6.7 静态内部类
外部类装载,静态内部类不会立即被装载,外部类调用getInstance()时,静态内部类被装载,且只装载一次,且装载时线程安全
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
}
}
//静态内部类完成,推荐使用
class Singleton{
//构造器私有化
public Singleton() {
}
//写一个静态内部类,该类中有一个静态属性 Singleton
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
6.8 枚举
public class SingletonTest08 {
public static void main(String[] args) {
Singleton instance = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance == instance2);
instance.sayOK();
}
}
//使用枚举,可以实现单例,推荐
enum Singleton {
INSTANCE;//属性
public void sayOK(){
System.out.println("ok~");
}
}
6.9 总结
在JDK中RunTime类使用了饿汉式
7 工厂设计模式
7.1 简单工厂模式
传统方式
Pizza
//将Pizza 类做成抽象
public abstract class Pizza {
protected String name;
//准备原材料,不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void bake(){
System.out.println(name + " baking");
}
public void cut(){
System.out.println(name + " cutting");
}
public void box(){
System.out.println(name + " boxing");
}
public void setName(String name){
this.name = name;
}
}
GreekPizza
public class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作希腊披萨 准备原材料");
}
}
CheesePizza
public class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作奶酪披萨 准备原材料");
}
}
OrderPizza
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 {
break;
}
//输出pizza制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}
//写一个方法,可以获取客户希望订购的披萨种类
private String getType(){
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type: ");
String str = null;
str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
PizzaStore
//相当于一个客户端,发出订购
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza();
}
}
运行结果
PepperPizza
public class PepperPizza extends Pizza{
@Override
public void prepare() {
System.out.println("给胡椒披萨准备原材料");
}
}
SimpleFactory
//简单工厂类
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;
}
}
OrderPizza
public class OrderPizza {
//定义一个简单工厂对象
SimpleFactory simpleFactory;
Pizza pizza = null;
//构造器
public OrderPizza(SimpleFactory simpleFactory){
setFactory(simpleFactory);
}
public void setFactory(SimpleFactory simpleFactory){
String orderType = "";//用户输入的
this.simpleFactory = simpleFactory; //设置简单工厂对象
do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
//输出pizza
if(Objects.nonNull(pizza)){ //订购成功
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 type: ");
String str = null;
str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
PizzaStore
//相当于一个客户端,发出订购
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new SimpleFactory());
System.out.println("退出程序~~");
}
}
运行结果
7.2 工厂方法模式
Pizza
//将Pizza 类做成抽象
public abstract class Pizza {
protected String name;
//准备原材料,不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void bake(){
System.out.println(name + " baking");
}
public void cut(){
System.out.println(name + " cutting");
}
public void box(){
System.out.println(name + " boxing");
}
public void setName(String name){
this.name = name;
}
}
BJCheesePizza
public class BJCheesePizza extends Pizza{
@Override
public void prepare() {
setName("北京的奶酪Pizza");
System.out.println(" 北京的奶酪Pizza 准备原材料");
}
}
BJPepperPizza
public class BJPepperPizza extends Pizza{
@Override
public void prepare() {
setName("北京的胡椒Pizza");
System.out.println(" 北京的胡椒Pizza 准备原材料");
}
}
LDCheesePizza
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
setName("伦敦的奶酪Pizza");
System.out.println(" 伦敦的奶酪Pizza 准备原材料");
}
}
LDPepperPizza
public class LDPepperPizza extends Pizza{
@Override
public void prepare() {
setName("伦敦的胡椒Pizza");
System.out.println(" 伦敦的胡椒Pizza 准备原材料");
}
}
OrderPizza
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 type: ");
String str = null;
str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
BJOrderPizza
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();
}
return pizza;
}
}
LDOrderPizza
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();
}
return pizza;
}
}
PizzaStore
public class PizzaStore {
public static void main(String[] args) {
//创建北京口味的各种Pizza
new BJOrderPizza();
//创建伦敦口味的各种Pizza
//new LDOrderPizza();
}
}
运行结果
7.3 抽象工厂模式
AbsFactory
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
//让下面的工厂子类来 具体实现
public Pizza createPizza(String orderType);
}
BJFactory
//这是工厂子类
public class BJFactory implements AbsFactory{
@Override
public Pizza createPizza(String orderType) {
System.out.println("使用的是抽象工厂模式");
Pizza pizza = null;
if(orderType.equals("cheese")){
pizza = new BJCheesePizza();
}else if(orderType.equals("pepper")){
pizza = new BJPepperPizza();
}
return pizza;
}
}
LDFactory
//这是工厂子类
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
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(Objects.nonNull(pizza)){
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 type: ");
String str = null;
str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
PizzaStore
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new BJFactory());
}
}
运行结果
8 原型模式
8.1 案例
输出结果
Sheep.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sheep implements Cloneable{
private String name;
private int age;
private String color;
/**
* 克隆该实例,使用默认的clone方法来完成
* @return
*/
@Override
protected Object clone(){
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
}catch (Exception e){
System.out.println(e.getMessage());
}
return sheep;
}
}
test
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep sheep2 = (Sheep) sheep.clone();
Sheep sheep3 = (Sheep) sheep.clone();
Sheep sheep4 = (Sheep) sheep.clone();
Sheep sheep5 = (Sheep) sheep.clone();
System.out.println(sheep);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
System.out.println(sheep5);
}
}
以后实体类增加了一个属性,可以直接克隆
8.2 应用
8.3 浅拷贝和深拷贝
方式1
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();
}
}
DeepProtoType
public class DeepProtoType implements Serializable,Cloneable {
public String name;
public DeepCloneableTarget deepCloneableTarget;//引用类型
public DeepProtoType() {
}
//深拷贝 - 方式1 使用clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//这里完成对基本数据类型(属性)和String的克隆
deep = super.clone();
//对引用类型属性,进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone();
return deepProtoType;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
DeepProtoType p1 = new DeepProtoType();
p1.name = "fp";
p1.deepCloneableTarget = new DeepCloneableTarget("大牛","小牛");
//方式1 完成深拷贝
DeepProtoType p2 = (DeepProtoType) p1.clone();
System.out.println("p1.name="+p1.name+" p1.deepCloneableTarget="+p1.deepCloneableTarget.hashCode());
System.out.println("p2.name="+p2.name+" p2.deepCloneableTarget="+p2.deepCloneableTarget.hashCode());
}
}
实现了深拷贝
方式2
DeepProtoType
public class DeepProtoType implements Serializable,Cloneable {
public String name;
public DeepCloneableTarget deepCloneableTarget;//引用类型
public DeepProtoType() {
}
//深拷贝 - 方式1 使用clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//这里完成对基本数据类型(属性)和String的克隆
deep = super.clone();
//对引用类型属性,进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone();
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) {
e.printStackTrace();
return null;
} finally {
//关闭流
try {
if (bos != null) {
bos.close();
}
if (oos != null) {
oos.close();
}
if (bis != null) {
bis.close();
}
if (ois != null) {
ois.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
Client
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
DeepProtoType p1 = new DeepProtoType();
p1.name = "fp";
p1.deepCloneableTarget = new DeepCloneableTarget("大牛","小牛");
//方式1 完成深拷贝
/*DeepProtoType p2 = (DeepProtoType) p1.clone();
System.out.println("p1.name="+p1.name+" p1.deepCloneableTarget="+p1.deepCloneableTarget.hashCode());
System.out.println("p2.name="+p2.name+" p2.deepCloneableTarget="+p2.deepCloneableTarget.hashCode());*/
//方式2 完成深拷贝
DeepProtoType p3 = (DeepProtoType)p1.deepClone();
System.out.println("p1.name="+p1.name+" p1.deepCloneableTarget="+p1.deepCloneableTarget.hashCode());
System.out.println("p3.name="+p3.name+" p3.deepCloneableTarget="+p3.deepCloneableTarget.hashCode());
}
}
序列化方式深拷贝成功(如果属性是多个对象类型,更适用,推荐)
9 建造者模式
AbstractHouse
public abstract class AbstractHouse {
//打地基
public abstract void buildBasic();
//建墙
public abstract void buildWalls();
//建屋顶
public abstract void roofed();
public void build(){
buildBasic();
buildWalls();
roofed();
}
}
CommonHouse
public class CommonHouse extends AbstractHouse {
@Override
public void buildBasic()
{
System.out.println(" 普通房子打地基");
}
@Override
public void buildWalls()
{
System.out.println(" 普通房子砌墙");
}
@Override
public void roofed()
{
System.out.println(" 普通房子盖屋顶");
}
}
Client
public class Client {
public static void main(String[] args) {
CommonHouse commonHouse = new CommonHouse();
commonHouse.build();
}
}
House 产品
//产品 -> Product
@Data
@AllArgsConstructor
@NoArgsConstructor
public class House {
private String basic;
private String wall;
private String roofed;
}
HouseBuilder 建造者
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;
}
}
两个具体建造者
CommonHouse
public class CommonHouse extends HouseBuilder{
@Override
public void buildBasic() {
System.out.println("普通房子打地基");
}
@Override
public void buildWalls() {
System.out.println("普通房子砌墙");
}
@Override
public void roofed() {
System.out.println("普通房子盖屋顶");
}
}
HighBuilding
public class HighBuilding extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("高楼的基座");
}
@Override
public void buildWalls() {
System.out.println("高楼的墙");
}
@Override
public void roofed() {
System.out.println("高楼的屋顶");
}
}
HouseDirector 指挥者
//指挥者,这里去指定建房子的流程,返回产品
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(){
//1. 打地基
houseBuilder.buildBasic();
//2. 砌墙
houseBuilder.buildWalls();
//3. 封顶
houseBuilder.roofed();
//建造房子将产品(房子)返回
return houseBuilder.buildHouse();
}
}
Client 客户
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("-----------------------");
//盖高楼
HighBuilding highBuilding = new HighBuilding();
//重置建造者
houseDirector.setHouseBuilder(highBuilding);
//完成盖房子,返回产品(高楼)
House house2 = houseDirector.constructHouse();
}
}
10 适配器模式
10.1 类适配器模式
Voltage220V
//被适配器
public class Voltage220V {
// 输出220V电压
public int output220V(){
int src=220;
System.out.println("电压="+src+"伏特");
return src;
}
}
IVoltage5V接口
public interface IVoltage5V {
public int output5V();
}
VoltageAdapter
//适配器类
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
@Override
public int output5V() {
int srcV = output220V();//获取到220V电压
int dstV = srcV / 44; //转成5V
return dstV;
}
}
Phone
public class Phone {
public void charging(IVoltage5V v5){
int adapterV5 = v5.output5V();
if(adapterV5 == 5){
System.out.println("充电中");
}else{
System.out.println("充电失败");
}
}
}
Client
public class Client {
public static void main(String[] args) {
System.out.println("类适配器模式测试:");
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
10.2 对象适配器模式
Voltage220V
public class Voltage220V {
// 输出220V电压
public int output220V(){
int src=220;
System.out.println("电压="+src+"伏特");
return src;
}
}
IVoltage5V
// 适配接口
public interface IVoltage5V {
public int output5V();
}
VoltageAdapter
//适配器类
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
//通过构造器,传入一个220V的实例
public VoltageAdapter(Voltage220V voltage220V){
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int dst = 0;
if(Objects.nonNull(voltage220V)){
//获取220V的电压
int src = voltage220V.output220V();
//转成5V
dst = src / 44;
System.out.println("使用对象适配器适配220V电压到5V");
}
return dst;
}
}
Phone
public class Phone {
public void charging(IVoltage5V v5){
int adapterV5 = v5.output5V();
if(adapterV5 == 5){
System.out.println("充电中");
}else{
System.out.println("充电失败");
}
}
}
Client
public class Client {
public static void main(String[] args) {
System.out.println("对象适配器模式测试:");
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
10.3 接口适配器模式
Interface4
public interface Interface4 {
public void m1();
public void m2();
public void m3();
public void m4();
}
AbsAdapter
//在AbsAdapter 我们将Interface4的方法进行默认实现
public abstract class AbsAdapter implements Interface4{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
Client
public class Client {
public static void main(String[] args) {
//抽象类不能直接实例化,但可以通过继承和匿名内部类的方式来创建它的实例。
//通过匿名内部类创建抽象类的实例时,必须实现所有抽象方法
//对于抽象类中的普通方法,可以选择性地重写,但不是必须的
AbsAdapter absAdapter = new AbsAdapter() {
//只需要去覆盖我们 需要使用 接口方法
@Override
public void m1() {
System.out.println("使用了m1的方法");
}
};
absAdapter.m1();
}
}
11 桥接模式
11.1 简介
11.2 代码实现
Brand
public interface Brand {
void open();
void close();
void call();
}
Vivo
public class Vivo implements Brand{
@Override
public void open() {
System.out.println("vivo手机开机");
}
@Override
public void close() {
System.out.println("vivo手机关机");
}
@Override
public void call() {
System.out.println("vivo手机打电话");
}
}
XiaoMi
public class XiaoMi implements Brand{
@Override
public void open() {
System.out.println("小米手机开机");
}
@Override
public void close() {
System.out.println("小米手机关机");
}
@Override
public void call() {
System.out.println("小米手机打电话");
}
}
Phone
public abstract class Phone {
//组合品牌
private Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
public void open(){
this.brand.open();
}
public void close(){
this.brand.close();
}
public void call(){
this.brand.call();
}
}
FoldedPhone
// 折叠式手机类,继承抽象类Phone
public class FoldedPhone extends Phone {
/**
* 当你创建一个子类时,编译器会隐式地调用父类的无参构造方法。如果父类没有无参构造方法,
* 子类必须显式地调用父类的其中一个构造方法,并且要匹配父类构造方法所需要的参数。
* 由于 Phone 类没有无参构造方法,所以 FoldedPhone 类必须显式地调用 Phone 类的构造方法,
* 并传递一个 Brand 对象作为参数。这就是为什么 FoldedPhone 类必须实现构造方法,并且这个构造方法要调用 super(brand)。
* @param brand
*/
public FoldedPhone(Brand brand) {
super(brand);
}
@Override
public void open() {
super.open();
System.out.println("折叠式手机开机");
}
@Override
public void close() {
super.close();
System.out.println("折叠式手机关机");
}
@Override
public void call() {
super.call();
System.out.println("折叠式手机打电话");
}
}
Client
public class Client {
public static void main(String[] args) {
//获取折叠式手机(样式 + 品牌)
Phone phone = new FoldedPhone(new XiaoMi());
phone.open();
phone.call();
System.out.println("--------------------");
Phone phone1 = new FoldedPhone(new Vivo());
phone1.open();
phone1.call();
phone1.close();
}
}
新增一个手机样式
UpRightPhone
public class UpRightPhone extends Phone{
public UpRightPhone(Brand brand) {
super(brand);
}
@Override
public void open() {
System.out.println("直立手机开机");
}
@Override
public void close() {
super.close();
System.out.println("直立手机关机");
}
@Override
public void call() {
super.call();
System.out.println("直立手机打电话");
}
}
Client
public class Client {
public static void main(String[] args) {
//获取折叠式手机(样式 + 品牌)
Phone phone = new FoldedPhone(new XiaoMi());
phone.open();
phone.call();
System.out.println("--------------------");
Phone phone1 = new FoldedPhone(new Vivo());
phone1.open();
phone1.call();
phone1.close();
System.out.println("--------------------");
Phone phone2 = new UpRightPhone(new XiaoMi());
phone2.open();
phone2.call();
phone2.close();
System.out.println("--------------------");
Phone phone3 = new UpRightPhone(new Vivo());
phone3.open();
phone3.call();
phone3.close();
}
}
11.3 实际运用
12 装饰者模式
12.1 简介
12.2 案例
Drink
public abstract class Drink {
public String des;//描述
private float price = 0.0f;//价格
//计算费用的抽象方法
//子类必须实现该方法
public abstract float cost();
}
Coffee
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
咖啡种类
LongBlack
public class LongBlack extends Coffee{
public LongBlack() {
setDes("美式咖啡");
setPrice(5.0f);
}
}
ShortBlack
public class ShortBlack extends Coffee{
public ShortBlack() {
setDes("ShortBlack");
setPrice(5.0f);
}
}
Espresso
public class Espresso extends Coffee{
public Espresso() {
setDes("意大利咖啡");
setPrice(6.0f);
}
}
装饰者
Decorator
public class Decorator extends Drink{
private Drink drink;
public Decorator(Drink drink) { //组合
this.drink = drink;
}
@Override
public float cost() {
//getPrice() 自己的价格
return super.getPrice() + drink.cost();
}
@Override
public String getDes() {
//super.des 自己的描述 drink.getDes() 输出被装饰者的信息
return super.des + " " + super.getPrice() + " && " + drink.getDes();
}
}
调料
Chocolate
public class Chocolate extends Decorator {
public Chocolate(Drink obj) {
super(obj);
setDes("巧克力");
setPrice(3.0f); //调味品的价格
}
}
Milk
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
Soy
public class Soy extends Decorator {
public Soy(Drink obj) {
super(obj);
setDes("豆浆");
setPrice(1.5f);
}
}
测试
CoffeeBar
public class CoffeeBar {
public static void main(String[] args) {
//装饰者模式下的订单: 2份巧克力 + 1份牛奶的LongBlack
//1. 点一份LongBlack
Drink order = new LongBlack();
System.out.println("费用1:" + order.cost());
System.out.println("描述1:" + order.getDes());
//2. 加入一份牛奶
order = new Milk(order);
System.out.println("order 加入一份牛奶 费用2:" + order.cost());
System.out.println("order 加入一份牛奶 描述2:" + order.getDes());
//3. 加入一份巧克力
order = new Chocolate(order);
System.out.println("order 加入一份牛奶 加入一份巧克力 费用3:" + order.cost());
System.out.println("order 加入一份牛奶 加入一份巧克力 描述3:" + order.getDes());
//4. 加入一份巧克力
order = new Chocolate(order);
System.out.println("order 加入一份牛奶 加入2份巧克力 费用4:" + order.cost());
System.out.println("order 加入一份牛奶 加入2份巧克力 描述4:" + order.getDes());
}
}
12.3 应用
13 组合模式
13.1 简介
13.2 代码实现
OrganizationComponent
@Data
@NoArgsConstructor
public abstract class OrganizationComponent {
protected String name;//名字
protected String desc;//说明
public OrganizationComponent(String name, String desc) {
this.name = name;
this.desc = desc;
}
protected void add(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
//方法print,做成抽象的,子类都需要实现
protected abstract void print();
}
University
//University 就是 Composite, 可以管理College
public class University extends OrganizationComponent{
List<OrganizationComponent> organizationComponents = new ArrayList();
public University(String name, String des) {
super(name, des);
}
@Override
protected void add(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDesc() {
return super.getDesc();
}
//print方法,就是输出University 包含的学院
@Override
protected void print() {
System.out.println("------" + getName() + "------");
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
College
public class College extends OrganizationComponent{
List<OrganizationComponent> organizationComponents = new ArrayList();
public College(String name, String des) {
super(name, des);
}
@Override
protected void add(OrganizationComponent organizationComponent) {
//将来实际业务中,College的add 和 University 的add 不一定完全一样
organizationComponents.add(organizationComponent);
}
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDesc() {
return super.getDesc();
}
//print方法,就是输出University 包含的学院
@Override
protected void print() {
System.out.println("------" + getName() + "------");
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
Department
public class Department extends OrganizationComponent{
public Department(String name, String desc) {
super(name, desc);
}
// add, remove就不用写了,因为他是叶子节点
@Override
public String getName() {
return super.getName();
}
@Override
public String getDesc() {
return super.getDesc();
}
@Override
protected void print() {
System.out.println(getName());
}
}
Client
public class Client {
public static void main(String[] args) {
//从大到小创建对象 学校
OrganizationComponent university = new University("清华大学", "中国顶级大学");
//创建学院
OrganizationComponent computerCollege = new College("计算机学院", "计算机学院");
OrganizationComponent infoEngineerCollege = new College("信息工程学院", "信息工程学院");
//创建各个学院下面的系(专业)
computerCollege.add(new Department("软件工程", "软件工程不错"));
computerCollege.add(new Department("网络工程", "网络工程不错"));
computerCollege.add(new Department("计算机科学与技术", "计算机科学与技术不错"));
infoEngineerCollege.add(new Department("通信工程", "通信工程不错"));
infoEngineerCollege.add(new Department("信息工程", "信息工程不错"));
//将学院加入到学校
university.add(computerCollege);
university.add(infoEngineerCollege);
university.print();
}
}
运行结果