- Java的设计模式
- 1. 设计模式的七大原则
- 1.1.单一职责原则
- 1.1.1. 基本介绍
- 1.1.2. 单一职责原则注意事项和细节
- 1.2. 接口隔离原则
- 1.2.2. 代码实现
- 1.3. 依赖倒置原则
- 1.3.2. 代码实现
- 1.4. 里式替换原则
- 1.5. 开闭原则
- 1.5.1. 介绍
- 1.5.2. 代码实现
- 1.6. 迪米特原则
- 1.6.1 介绍
- 1.6.2. 代码
- 1.7 合成复用原则
- 2. 单例模式
- 2.1 介绍
- 2.2 懒汉式双重校验锁机制
- 2.2. 饿汉式
- 2.3. 单例模式注意事项和细节说明
- 3. 工厂模式
- 4. 原型模式
- 4.1. 介绍
- 4.2. 浅拷贝
- 4.3. 深拷贝
- 4.4.原型模式的注意事项和细节
- 5.1. 建造者模式
- 5.2. 代码实现
- 6. 适配器模式
- 6.1. 基本介绍
- 6.2. 类适配器模式
- 6.3. 对象适配器
- 6.4. 接口适配器
1. 设计模式的七大原则 1.1.单一职责原则 1.1.1. 基本介绍
对类来说的,即一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2。
当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为
A1,A2
- 降低类的复杂度,一个类只负责一项职责。
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违
反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则
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();
}
}
1.3. 依赖倒置原则
1.3.2. 代码实现
package com.ckack.DesignPatterns.principle.inversion;
/**
* @author: ckack
* @date: 2022/4/17 13:40
*/
public class DependencyInversion {
public static void main(String[] args) {
//1. 构造方法
// Person person = new Person(new Email());
// 2. Setter 方法
Person person = new Person();
person.setI(new WeiXin());
person.receive();
}
}
interface IReceiver {
String getInfo();
}
class Email implements IReceiver {
@Override
public String getInfo() {
return "电子邮箱:Hello world";
}
}
class WeiXin implements IReceiver {
@Override
public String getInfo() {
return "WeiXin:Hello world";
}
}
class Person {
private IReceiver i;
// 1. 构造方法
public Person(IReceiver i) {
this.i = i;
}
public Person() {
}
public void setI(IReceiver i) {
this.i = i;
}
public void receive() {
System.out.println(i.getInfo());
}
}
1.4. 里式替换原则
1.5. 开闭原则
1.5.1. 介绍
- 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
- 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用
方)。用抽象构建框架,用实现扩展细节。 - 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已
有的代码来实现变化。 - 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则
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(" 绘制其它图形 ");
}
}
1.6. 迪米特原则
1.6.1 介绍
- 一个对象应该对其他对象保持最少的了解
- 类与类关系越密切,耦合度越大
- 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的
越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内
部。对外除了提供的public 方法,不对外泄露任何信息 - 迪米特法则还有个更简单的定义:只与直接的朋友通信
- 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,
我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合
等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而
出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量
的形式出现在类的内部。
package com.atguigu.principle.demeter.improve;
import java.util.ArrayList;
import java.util.List;
//客户端
public class Demeter1 {
public static void main(String[] args) {
System.out.println("~~~使用迪米特法则的改进~~~");
//创建了一个 SchoolManager 对象
SchoolManager schoolManager = new SchoolManager();
//输出学院的员工id 和 学校总部的员工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}
//学校总部员工类
class Employee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//学院的员工类
class CollegeEmployee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//管理学院员工的管理类
class CollegeManager {
//返回学院的所有员工
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 list
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工id= " + i);
list.add(emp);
}
return list;
}
//输出学院员工的信息
public void printEmployee() {
//获取到学院员工
List<CollegeEmployee> list1 = getAllEmployee();
System.out.println("------------学院员工------------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
}
}
//学校管理类
//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则
class SchoolManager {
//返回学校总部的员工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();
for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 list
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("------------学校总部员工------------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}
1.7 合成复用原则
2. 单例模式
参考:https://blog.csdn.net/m0_57310550/article/details/123500229?spm=1001.2014.3001.5502
2.1 介绍
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
2.2 懒汉式双重校验锁机制
package com.ckack.DesignPatterns.simple.type3;
/**
*懒汉式双重校验锁机制
* @author: ckack
* @date: 2022/4/19 21:41
*/
public class SingletonTest03 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance1 == instance);
System.out.println(instance1.hashCode());
System.out.println(instance.hashCode());
}
}
class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
// 当使用该方法是 才去创建
/**
* 懒汉式 加入synchronized 同步处理代码 解决线程安全问题
*/
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
2.2. 饿汉式
package com.ckack.DesignPatterns.simple.type1;
/**
* @author: ckack
* @date: 2022/4/19 21:22
*/
public class SingletonTest01 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance1 == instance);
System.out.println(instance1.hashCode());
System.out.println(instance.hashCode());
}
}
/**
* 方法1
* 饿汉式(静态变量)
* 缺点:在类装载的时候就完成实例化,没有达到懒加载效果 如果都没用的话 会造成 内存浪费
* */
class Singleton {
private Singleton() {
}
private final static Singleton instance = new Singleton();
//对外提供一个公有的静态方法
public static Singleton getInstance() {
return instance;
}
}
/**
* 方法二
* 内部类
* @author: ckack
* @date: 2022/4/20 21:53
*/
public class Singleton2 {
private static class SingletonInstance {
private static final Singleton2 INSTANCE = new Singleton();
}
public static Singleton2 getInstance() {
return SingletonInstance.INSTANCE;
}
}
2.3. 单例模式注意事项和细节说明
1) 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,
使用单例模式可以提高系统性能
2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),
但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)
3. 工厂模式
4. 原型模式
4.1. 介绍
1) 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象
2) 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
3) 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone()
4.2. 浅拷贝
通过实现Clone接口
package com.ckack.DesignPatterns.prototype;
/**
* @author: ckack
* @date: 2022/4/21 20:35
*/
public class Sheep implements Cloneable {
private String name;
private String age;
private String color;
public Sheep friend;
public Sheep() {
}
public Sheep(String name, String age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String 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 + '\'' +
", friend=" + friend +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep = (Sheep) super.clone();
return sheep;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("aaa", "111", "222");
sheep.friend = new Sheep("friend", "22", "222");
Sheep sheep2 = (Sheep) sheep.clone();
System.out.println(sheep2.friend.hashCode());
System.out.println(sheep.friend.hashCode());
}
}
4.3. 深拷贝
package com.ckack.DesignPatterns.prototype.deepclone;
import java.io.Serializable;
/**
* @author: ckack
* @date: 2022/4/21 20:52
*/
public class DeepCloneableTarget implements Cloneable, Serializable {
private static final long sericaVersionUID = 1L;
private String cloneName;
private String cloneClass;
public DeepCloneableTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//##############################################################
package com.ckack.DesignPatterns.prototype.deepclone;
import java.io.*;
/**
* @author: ckack
* @date: 2022/4/21 20:56
*/
public class DeepProtoType implements Cloneable, Serializable {
public String name;
public DeepCloneableTarget deepCloneableTarget;
//1. 使用clone的方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//完成对基本数据类型的克隆
deep = super.clone();
//对引用类型的属性进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
return deep;
}
//2. 通过对象的序列化 实习深拷贝
public Object deepClone() throws IOException {
//创建流对象
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 deepProtoType = (DeepProtoType) ois.readObject();
return deepProtoType;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
bos.close();
oos.close();
bis.close();
ois.close();
}
}
}
//######################################################################
import java.io.IOException;
/**
* @author: ckack
* @date: 2022/4/21 21:08
*/
public class Client {
public static void main(String[] args) throws IOException {
DeepProtoType deepProtoType = new DeepProtoType();
deepProtoType.deepCloneableTarget = new DeepCloneableTarget("11", "22");
deepProtoType.name = "231";
DeepProtoType o = (DeepProtoType) deepProtoType.deepClone();
System.out.println(deepProtoType.deepCloneableTarget.hashCode());
System.out.println(o.deepCloneableTarget.hashCode());
}
}
4.4.原型模式的注意事项和细节
1) 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
2) 不用重新初始化对象,而是动态地获得对象运行时的状态
3) 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码
4) 在实现深克隆的时候可能需要比较复杂的代码
5) 缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp原则.
5.1. 建造者模式
5.2. 代码实现
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;
}
}
public class CommonHouse extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("普通房子打地基5米");
}
@Override
public void buildWalls() {
System.out.println("普通房子砌墙10cm ");
}
@Override
public void roofed() {
System.out.println("普通房子屋顶");
}
}
package com.ckack.DesignPatterns.construction;
public class HighBuilding extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("高楼的打地基100米");
}
@Override
public void buildWalls() {
System.out.println("高楼的砌墙20cm");
}
@Override
public void roofed() {
// TODO Auto-generated method stub
System.out.println("高楼的透明屋顶");
}
}
package com.ckack.DesignPatterns.construction;
// 抽象的建造者
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;
}
}
public class HouseDirector {
HouseBuilder houseBuilder = null;
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
public House constructHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.buildHouse();
}
}
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);
houseDirector.constructHouse();
}
}
6. 适配器模式
6.1. 基本介绍
1) 适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)
2) 适配器模式属于结构型模式
3) 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
6.2. 类适配器模式
//源
public abstract class Voltage220 {
int output220() {
int src = 220;
System.out.println(String.format("电压:%s", src));
return src;
}
}
//
//输出
public interface Voltage5V {
int output5V();
}
//适配器 实现接口
public class ClassAdapter extends Voltage220 implements Voltage5V{
@Override
public int output5V() {
int src = output220();
src = src / 44;
return src;
}
}
public class phone {
public void Charing(Voltage5V v) {
int i = v.output5V();
System.out.println(i);
}
}
public class client {
public static void main(String[] args) {
phone phone = new phone();
phone.Charing(new ClassAdapter());
}
}
6.3. 对象适配器
public class Voltage220 {
int output220() {
int src = 220;
System.out.println(String.format("电压:%s", src));
return src;
}
}
public interface Voltage5V {
int output5V();
}
public class ClassAdapter implements Voltage5V {
private Voltage220 voltage220;
public void setVoltage220(Voltage220 voltage220) {
this.voltage220 = voltage220;
}
@Override
public int output5V() {
int src = this.voltage220.output220();
src = src / 44;
return src;
}
}
public class phone {
public void Charing(Voltage5V v) {
int i = v.output5V();
System.out.println(i);
}
}
public class client {
public static void main(String[] args) {
phone phone = new phone();
ClassAdapter classAdapter = new ClassAdapter();
classAdapter.setVoltage220(new Voltage220());
phone.Charing(classAdapter);
}
}
6.4. 接口适配器
public interface interface1 {
void mi();
void m2();
void m3();
void m4();
}
public abstract class AbsAdapter implements interface1{
@Override
public void mi() {
System.out.println("father.mi");
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
public class interfaceadapter extends AbsAdapter {
@Override
public void mi() {
System.out.println("m1");
}
}
public class client {
public static void main(String[] args) {
interfaceadapter interfaceadapter = new interfaceadapter();
interfaceadapter.mi();
AbsAdapter absAdapter = new AbsAdapter(){
@Override
public void mi(){
System.out.println("son");
}
};
absAdapter.mi();
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)