目录
里氏替换原则(lsp)定义:(基类的引用能够透明的被子类对象所替换)
接口隔离原则:客户端不应该依赖它不需要的一些接口 接口要单一
2023年3月10日
GOF是什么?
- GOF是指设计模式的四位创始人(Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)的首字母缩写。他们共同编写了《设计模式:可复用面向对象软件的基础》一书,该书成为了设计模式领域的经典之作。在该书中,他们提出了23种常用的设计模式,分为创建型、结构型和行为型三类。这些设计模式被广泛应用于软件开发中,以提高软件的可复用性、可维护性、可扩展性等方面的质量。
模式分为哪几种?
- 创建型 结构型 行为型
面向对象设计原则有哪几个?分别是什么?
一共有7个
- 1.单一职责原则
- 2.开闭原则
- 3.里氏原则
- 4.接口隔离原则
- 5.依赖倒转原则
- 6.
开闭原则分析(上课)
- 1.抽象化是开闭原则的
- 2.相对稳定的抽象层(抽象类或接口)+灵活的具体层
- 3.对可变性封装原则:找到系统的可变因素并将其封装起来
- 框架:IOC容器
- 反射技术:动态运行期获取类信息的一种方式。
- //反射:动态运行期获取类的信息的一种技术
下节课编写代码
- Class<?> aClass = Class.forName(cName);
- //创建对象 所有类的对象
- Object obj=aClass.newInstance();
- return obj;
里氏替换原则(lsp LOD)定义:(基类的引用能够透明的被子类对象所替换)
- //父类 基类
- //父类的引用被子类替换 10行 透明解释:行为方法不变
- 解决方案:
- 1.不能重写父类的方法 语法:final
- 2.父类写一个方法实现了,约束规范。
- 3.可以扩展(新增)
- 4.取消原有的继承关系,重写设计关系
1.里氏替换原则实现开闭原则的具体举措
2.保证行为的的正确性
3.保证了程序的可复用性
- 依赖倒转原则(dip)
- Sprng (IOC(DI) AOP)
- 定义:面向接口编程
- 具体:MVC Service Impl
解决方案:
1.每个类尽量提供接口或抽象类,或者两者都具备
2.变量的声明 类型尽量是接口或者是抽象类
3.任何类都不应该从具体类派生
4.如果一定要继承,尽量遵循里氏替换原则
依赖倒置原则的重要性
- 依赖倒置原则可以降低类间的耦合性。
- 依赖倒置原则可以提高系统的稳定性<
- 依赖倒置原则可以减少并行开发引起的风险。
- 依赖倒置原则可以提高代码的可读性和可维护性。
接口隔离原则:客户端不应该依赖它不需要的一些接口 接口要单一
- 解决方案:
- 不要定义大而全的接口,根据用户职责定义
- 1.接口尽量小要有限度,一个接口只服务于一个子模块或业务逻辑
- 2.了解环境,拒绝盲从
- 3.提高类聚,减少对外交互
- 4.接口更关注用户的需求,根据场景
- 单一职责原则:类的职责要单一 (关注类 )
- 单依职责提高代码的复用性
2023年3月14日第三周第一次课程
合成复用原则
定义:组合优先于继承 多实现 优于 单继承
接口由于抽象类
c++ 多继承 Java单继承
如果一定要继承,那就一定符合里式替换原则
迪米特法则(最少知识原则)尽可能的减少和交互的实体
- 要求一个软件实体应当尽可能少的与其他实体发生相互作用
- 降低系统的耦合度,类和类 引入第三者
总结:
7个设计原则
- 开闭原则:基石 对扩展开发 对修改关闭
- 不要重写父类的方法:里式替换原则(不改写行为方式) Final
- 依赖倒转:面向接口编程
- 接口隔离原则:接口的定义尽可能小,根据用户需求
- 类的单一职责原则:
- 迪米特法则;
- 合成复用原则:组合优于继承
单例模式
- 国家总统只能有一个
- 目的:使得类的一个对象成为当前系统的唯一一个实例
package practise.singleton;
public class SingletonTest {
public static void main(String[] args) {
System.out.println(President.getPresident());
System.out.println(President.getPresident());
System.out.println(President.getPresident());
}
}
//目的:保证只存在一个实例
class President{
//类型为自身的成员变量 成员变量默认null
private static President president;
//成员变量不需要赋值 false 0 0.0
//构造方法私有化
private President(){}
public static President getPresident(){
if(president==null){
president=new President();
}
return president;
}
}
单例模式
负载均衡服务器:单例
多线程并发的情况下有问题:
两个线程:main 主线程 gc线程
package practise.singleton;
public class SingletonTest {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(President.getPresident());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(President.getPresident());
}
}).start();
}
}
//目的:保证只存在一个实例
class President{
//类型为自身的成员变量 成员变量默认null
private static President president;
//成员变量不需要赋值 false 0 0.0
//构造方法私有化
private President(){}
public static President getPresident(){
if(president==null){
president=new President();
}
return president;
}
}
2023年3月17日提问
1、什么是单例模式?
- 单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供了全局访问点。
2、单例模式最基本的写法?且为什么?
- 1.构造方法私有化
- 外部不能创建对象
2.静态私有的(自身)成员变量
- 被静态方法调用
- 共有防止被修改
3。静态公共的成员方法 返回类型 自身
- 静态:外部没有办法调用非静态的成员方法
3、线程并发和并行的区别?
- 并行:一起运行
- 并发:交替运行
- 线程并发和并行都是指多个线程同时执行,但并发是指多个线程交替执行,每个线程都只执行一部分,然后切换到其他线程执行;而并行是指多个线程同时执行不同的任务,每个线程都可以独立地执行完整个任务。
- 原子性操作
4、线程不安全是什么意思?
- HashMap CurrentHashMap
- 线程不安全是指多个线程同时访问共享资源时可能会出现竞态条件,导致程序出现错误或不可预期的行为。
5、如果做到线程同步? 请列举一二
- 使用 synchronized 关键字来保证同一时间只有一个线程能够访问共享资源。
- 使用 Reentrant Lock 类来实现显式锁定,同样可以保证同一时间只有一个线程能够访问共享资源。
- 使用 volatile 关键字来保证多个线程之间的可见性,确保一个线程对共享变量的修改对其他线程是可见的。
单例模式
懒汉式
- 线程不安全
- 同步方法
- 双重检测
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重检测 synchronized 代码块 Volatile(jvm):禁止指令重排序
package practise.singleton.lanzy;
/*
* 线程不安全
*
* */
public class LazySingleton3 {
private static LazySingleton3 lazySingleton1=null;
private LazySingleton3(){
}
//原子性操作,不能分割的操作 synchronized
//synchronized 同步 加锁 多线程排队等待操作
//缺点:效率低
//synchronized
public static LazySingleton3 getInstance(){
if(lazySingleton1==null){
//线程1:执行同步代码块
//线程2:obj=null 等待进入同步代码块
synchronized(LazySingleton3.class){
//双重检测
if(lazySingleton1==null)
lazySingleton1=new LazySingleton3();
}
}
return lazySingleton1;
}
}
用三种方式分别创建负载均衡服务器 确保其单例
public class LoadBalancer1 {
public static volatile LoadBalancer1 loadBalancer=null;
private LoadBalancer1(){
}
public static synchronized LoadBalancer1 getInstance(){
if(loadBalancer==null){
loadBalancer=new LoadBalancer1();
}
return loadBalancer;
}
}
public class LoadBalancer2 {
public static volatile LoadBalancer2 loadBalancer=null;
private LoadBalancer2(){
}
public static LoadBalancer2 getInstance(){
if(loadBalancer==null){
synchronized (LoadBalancer2.class){
if(loadBalancer==null)
loadBalancer=new LoadBalancer2();
}
}
return loadBalancer;
}
}
public class LoadBalancer3 {
public static LoadBalancer3 loadBalancer=null;
private LoadBalancer3(){
}
public static LoadBalancer3 getInstance(){
loadBalancer=new LoadBalancer3();
return loadBalancer;
}
}
饿汉式单例模式总结:
问题:搜集行业的案例运用 讲原码 jdk 框架里(Spring)
期末加五分
1.线程不安全 缺点:线程不安全
2.线程同步方法 缺点:效率低
3双重检测 线程安全 缺点:volatile 禁止指令重排 提升了效率 缺点:效率相对较低
4.枚举类:完美 值得推荐
5.静态内部类:缺点:序列化和反序列化会产生多例
传参有问题 ?
6.
- 饿汉式:在类加载时就创建单例对象,线程安全,但会造成资源浪费。 优点:线程安全,避免了多线程同步的问题。 缺点:类加载时就创建单例对象,可能会造成资源浪费。
- 懒汉式:在第一次使用时才创建单例对象,存在线程安全问题。 优点:在第一次使用时才创建单例对象,避免了资源浪费。 缺点:存在线程安全问题,需要添加同步锁synchronized,效率低。
- 双重校验锁式:在懒汉式基础上加入同步锁和双重校验,既保证了线程安全,又避免了资源浪费。 优点:线程安全,避免了资源浪费。 缺点:实现过程较为复杂。
- 静态内部类式:利用类的静态属性和静态方法实现单例模式,线程安全且避免了资源浪费。 优点:线程安全,避免了资源浪费。 缺点:实现过程较为复杂。
- 枚举式:利用枚举类型的特性,实现线程安全且防止反射和序列化破坏单例模式。 优点:线程安全,防止反射和序列化破坏单例模式。 缺点:实现过程较为简单,但是不太常用。 综上所述,不同的单例模式写法各有优缺点,在具体实现时需要根据实际情况进行选择。
package Singletonkeenhuangdi.king;
public class KingTest {
public static void main(String[] args) {
String x=King11.getInstance("king11").getName();
}
}
class King11{
private static King11 king11;
private String name;
private King11(String name){
this.name=name;
}
public String getName() {
return name;
}
public static King11 getInstance(String name){
if(king11==null){
king11=new King11("king11");
}
return king11;
}
}
class King1{
private static King1 king1;
private String name;
private King1(String name){
this.name=name;
}
public String getName() {
return name;
}
public static King1 getInstance(){
if(king1==null){
king1=new King1("kangxi");
}
return king1;
}
}
class King2{
private static King2 king2=null;
private String name;
private King2(String name){
this.name=name;
}
public static King2 getInstance(){
if(king2==null){
synchronized (King2.class){
if(king2==null)
king2=new King2("yongzheng");
}
}
return king2;
}
}
class King3{
private volatile static King3 king3=null;
private String name;
private King3(String name){
this.name = name;
}
public String getName() {
return name;
}
private King3(){
}
public static King3 getInstance(){
if(king3==null){
synchronized (King3.class){
if(king3==null)
king3=new King3("king3");
}
}
return king3;
}
}
class King4{
private static King4 king4=null;
private String name;
private King4(String name){
this.name=name;
}
public String getName() {
return name;
}
// private static King4 getInstance(){
//
// }
}
class King33{
private static King33 king33=null;
private String name;
private King33(String name){
this.name=name;
}
public String getName() {
return name;
}
public static King33 getInstance(){
if(king33==null){
synchronized (King33.class){
if(king33==null)
king33=new King33("king33");
}
}
return king33;
}
}
//静态内部类
class King44{
private String name;
private King44(String name){
this.name=name;
}
private final static King44 king44=new King44("king44");
public static King4 getName(){
return King44.getName();
}
}
enum King5{
KING_5("king5");
String name;
private King5(String name){
this.name=name;
}
}
2023.3.28 课上提问
1、什么是单例模式? 请写出线程安全的单例模式的代码?
- 单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点来访问该实例。
2、为什么不允许从静态方法中访问非静态变量?
- 静态方法属于类,而非静态变量属于对象,静态方法不会访问到任何对象的状态,只能访问类的状态,因此无法访问非静态变量。而非静态变量的值是与对象相关的,需要通过对象来访问。
3、什么是指令重排序?
- 指令重排序是指编译器和处理器为了提高程序性能,在不改变程序执行结果的前提下重新安排指令的执行顺序的优化技术。由于现代处理器采用了乱序执行和多级缓存等技术,指令重排序可能会导致多线程程序出现意想不到的结果
4、 volatile 在哪里见过?有什么特点?是什么作用?
- 1.防止指令重排
- 什么作用?
- 1.保证可见性 不保证原子性
- 2.禁止指令重排序
5、重写和重载的区别?
- 重载(Overloading)是指在一个类中定义多个同名的方法,但这些方法的参数列表不同,编译器会根据不同的参数列表选择相应的方法进行调用。
- 重写(Overriding)是指子类对父类的方法进行重新实现,子类必须重写父类的方法名、参数列表和返回类型。重载的方法是同一个类中的方法,而重写的方法是父类和子类之间的方法。重写:权限不能低于父类权限
工厂模式(不符合开闭原则)
1.现实使用场景
专业越来越细(工厂的出现)
自给自足
2.定义
定义一个工厂类,根据传入参数的不同返回不同的产品
3.角色
三个角色:
工厂角色:负责创建不同的产品
抽象产品角色:定义抽象方法
具体产品角色:实体类
4.实践
5.找设计模式在jdk
工厂方法模式
定义:定义一个抽象工厂,根据参数的不同创建不同的子类。
每个工厂只生产一个产品
角色:
- 抽象产品:
- 具体产品:
- 抽象工厂:接口或者抽象类 定义工厂的具体业务
- 具体工厂:一个工厂只生产一个产品
- 案列:
- 缺点:类的数量成倍增加,
- 新需求:增加股价工厂
- 新需求1:增加一种 生产空调 海尔 海信
抽象工厂模式
一个厂生产多个产品(同一个品牌)
- 角色:
- 抽象产品:
- 具体产品:
- 抽象工厂:生产多个产品
- 具体工厂:
- 定义:一个工厂创建多个相关性产品(同一个品牌,同一个关系)
- 缺点:产品等级结构发生变化的时候不符合开闭原则 产品族发生变化的时候符合开闭原则
- 新需求:增加一个TCL工厂生产电视和空调(产品族 品牌)
- 修改具体过程和抽象工厂
- 优点:产品族发生变化的时候符合开闭原则
案例的分享:
建造者模式
角色:
抽象建造者:规范 定义对象的创建步骤和过程
具体建造者:实现
指挥者(组装车间):组装过程
产品:实体类(车辆)
建造者:建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象
单例模式:关注的对象的个数
工厂模式:工厂方法模式注重的是整体对象的创建方法
==(地址)
equal(内容)
public enum Vehicle {
XIANGLIANGBAN;
private String tyre;
private String engine;
private String Steering ;
/*private Vehicle(){};
private static V*/
public String getTyre() {
return tyre;
}
public void setTyre(String tyre) {
this.tyre = tyre;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
public String getSteering() {
return Steering;
}
public void setSteering(String steering) {
Steering = steering;
}
@Override
public String toString() {
return "Vehicle{" +
"tyre='" + tyre + '\'' +
", engine='" + engine + '\'' +
", Steering='" + Steering + '\'' +
'}';
}
}
public class VehicleBuilder extends Builder{
@Override
public void BuilderEngine() {
vehicle.setEngine("装发动机");
}
@Override
public void Buildertyre() {
vehicle.setTyre("装轮胎");
}
@Override
public void Buildersteering() {
vehicle.setSteering("装方向盘");
}
@Override
public Vehicle createVehicle() {
return vehicle;
}
}
第十二讲
创建者模式:
建造者模式
创建模式总结
定义、适用场景:客户端不需要知道复杂对象的内部结构和装配方法
创建流程很复杂 参数很多
角色:抽象建造者 具体建造者 指挥者产品
优缺点:
1.符合开闭原则 抽象工厂增加产品族符合开闭原则
2.将产品的构建过程和表示分开
缺点:
1.如果复杂对象构造过程不一致无法使用建造者模式
为什么?
IOC容器(框架用不到)
建造者模式在JDK中有很多应用,其中一些包括:
-
StringBuilder和StringBuffer类:这两个类都使用建造者模式来构建字符串对象。
-
DocumentBuilder类:这个类是Java API for XML Processing (JAXP)中的一部分,它使用建造者模式来构建XML文档对象。
-
Locale.Builder类:这个类用于构建Locale对象,它提供了一种更简单的方式来创建复杂的Locale对象。
-
DateTimeFormatterBuilder类:这个类用于构建DateTimeFormatter对象,它允许您通过添加不同的元素来定义日期格式。
-
GsonBuilder类:这个类是Google Gson库的一部分,它用于构建Gson对象,使其能够处理不同的JSON数据格式。
这些都是在JDK中使用建造者模式的一些示例,它们演示了建造者模式如何帮助您更容易地构建复杂的对象。
考试题目
众所周知,中国皇帝得服饰搭配很有讲究。这里我们分为两种:礼服、便服。每种服饰呢又有各自得特点而 且非常复杂,包含不同得衣服、靴子。 皇帝得装饰都是由内务府制作。根据衣服得类别有严格得制作流程。 每天皇帝出行前都会有尚衣监得太监,根据行程为皇帝进行穿搭(尚衣监类似于一个穿搭厂。每个太监就 类似于一个具体工厂负责具体不同场合得皇帝)。 例如李德全负责礼服穿搭(绣龙衣服)、赵昌负责便服穿搭等等。 请词学们根据行程安排完成皇帝穿搭。并进行代码编写完成上述需求。
(可变字符串)StringBuilder和StringBuffer的
指挥者(有时候隐藏指挥者 提早到抽象建造者里面了)
创建方法
方法返回类型
链式操作
StringBuilder和StringBuffer不需要指挥者(Director),它们可以直接使用链式操作来构建字符串对象。它们的创建方法都是new StringBuilder()或new StringBuffer(),返回类型为StringBuilder和StringBuffer对象。例如:
StringBuilder builder = new StringBuilder() .append("Hello") .append(" ") .append("World"); String result = builder.toString(); // "Hello World"
在上面的示例中,我们使用了StringBuilder对象,并通过连续的调用append()方法来构建一个字符串对象。最后,我们调用toString()方法获取最终结果。注意,由于StringBuilder和StringBuffer都是可变对象,因此可以使用链式操作来修改其内容。
结构性模式
结构性模式:关注如何将现有类或对象组织在一起形成更加强大的结构
- 适配器模式:将一个类的接口转换
- 桥接模式
- 装饰模式
- 代理模式
结构性模式-----适配器模式
- 定义:让两个不兼容的接口类可以一起工作
角色:
- 抽象目标类:IMath
- 适配器:MyMath
- 适配者:Third
//抽象目标类
public interface IMath {
//add 接口
double add(double a,double b);
int sub(int a,int b);
}
//适配器
public class Mymath implements IMath {
Third third;
Third1 third1;
@Override
public double add(double a, double b) {
return third.addFunc(a,b);
}
@Override
public int sub(int a, int b) {
return third1.sub(a,b);
}
}
//适配者
public class Third {
double addFunc(double a,double b){
return a+b;
}
}
适配器角色
1.适配者
2.适配者
3.抽象目标类
适配器有两种
类适配器
适配器继承了适配者 实现了目标抽象类
对象适配器
适配器引用适配者的一个对象实现了目标抽象类
1.适配器优缺点
- 将目标类和适配器类解耦,增加了类的复用性和透明性
- 系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都非常方便,符合开闭原则
- 可以将接口或数据转换代码从程序主要业务逻辑中分离,符合单一职责原则
- 类适配器模式的缺点是不能适配多个被适配类,也不能重写被适配类的方法
- 对象适配器模式的缺点是需要额外的引用来间接得到被适配类的方法,可能会影响效率
- 适配器模式可能会使系统变得复杂,增加了系统的理解难度
2.适配器在jdk或框架中的使用
handlerAdapeter的适配器
1.适配器HandlerAdapter解决了什么问题
-
适配器HandlerAdapter解决了Servlet中处理请求的问题。在Servlet中,处理不同类型请求需要实现不同的方法,例如处理GET请求需要实现doGet()方法,而处理POST请求需要实现doPost()方法。而适配器HandlerAdapter可以根据请求类型来选择调用对应的方法,从而解决了这个问题。
-
HandlerAdapter字面上的意思就是处理适配器,它的作用用一句话概括就是调用具体的方法对用户发来的请求来进行处理。当handlerMapping获取到执行请求的controller时,DispatcherServlte会根据controller对应的controller类型来调用相应的HandlerAdapter来进行处理。
2.Servlet核心调用方法?
Servlet核心调用方法是service()方法,该方法接收ServletRequest和ServletResponse两个参数,并根据请求类型调用对应的方法(例如doGet()、doPost()等)来处理请求。
/test get
1.Servlet接受到请求 映射到LoginServlet
2.其实统一进入的httpServlet的service方法 核心:根据请求方法的不同进入不同的方法
进入LoginServlet重写doget方法 没有重写 就进入httpservlet
2.调用doGet() 报405没找doGet方法
get post put delete restful规范
Servlet返回的是视图页面 一个请求一个Servlet
3.405 404 500 200 响应状态码 405 400是什么原因
响应状态码是HTTP协议中用于表示请求处理结果的数字代码。其中,200表示请求成功,404表示请求的资源不存在,405表示请求的方法不被允许,500表示服务器内部错误。400表示请求的语法有误,无法被服务器理解。
4.SpringMvc和Servlet有什么关系
Spring MVC是基于Servlet的框架,它使用Servlet来处理HTTP请求和响应。Spring MVC使用DispatcherServlet作为Servlet前端控制器,它接收所有的请求并将它们分发给不同的控制器进行处理。因此,Spring MVC和Servlet有密切的关系,可以看作是Servlet的增强和扩展。
Servlet 一个请求一个servlet
Spring url:
dispatcherServlet前端控制器
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
- 适配modelandview和用户返回的数据类型的匹配关系
- c/s 客户端 服务端
- b/s 浏览器 服务器 tomcat servlet
- servlet 处理服务力接受客户端请求
- 开发动态web资源的技术
第16讲
- 适配器优点缺点:
- 优点:将目标类和适配者类解耦
- 缺点:类适配只能适配一个适配者类
装饰着模式:
IO流 考试(装饰者模式和文件操作)
装饰者模式:装饰的是类
工具类的使用:很容易忘记。
IO:input :外部输入到java内存
output:
../a.txt上一级目录 /a.txt当前根目录 a.txt当前目录
日志输出console和文件里
1.大写输出 输出console和文件
2.xml格式输出 输出console和文件
四个类
UpconsoleLogger UpConslole
装饰者模式
装饰者Up xml 被装饰者:ConsoleLogger FileLogger
抽象组件(Component):定义一个抽象接口,用于表示组件对象的基本行为。在Java中通常是一个接口或抽象类。
具体组件(ConcreteComponent):实现抽象组件接口,定义一个具体的组件对象,可以被装饰器进行装饰。
抽象装饰器(Decorator):定义一个抽象装饰器接口,用于表示装饰器的基本行为。在Java中通常是一个抽象类,它包含一个抽象组件的引用。
具体装饰器(ConcreteDecorator):实现抽象装饰器接口,定义一个具体的装饰器对象,用来扩展组件对象的功能。
提问:抽象装饰者 为什么要 implements ILogger
为了实现多层装饰 意味着当前类转换成装饰者
//为什么 ILogger logger;
当前类装饰这个logger 增强他的功能 装饰者
为什么定义为abstruct class类 和 普通类
抽象方法 已经可以把相同的东西提取出来,每个子类的实现的功能不一样
为什么要super(logger)
两个待装饰对象 两个装饰品
开始
1.文件输入 输出流
2.目录拷贝:循环 文件拷贝
3.装饰者模式
复习
角色:
抽象组件(Component) :定义装饰方法的规范
被装饰者(ConcreteComponent) :Component的具体实现,也就是我们要装饰的具体对象。
装饰者组件(Decorator) :持有组件(Component)对象的实例引用,该类的职责就是为了装饰 具体组件对象,定义的规范。
具体装饰(ConcreteDecorator) :负责给构件对象装饰附加的功能。
抽象装饰者:实现了抽象构建 引用了一个构建对象
具体装饰者:
优缺点:
1.符合开闭原则
2.动态的进行多次装饰
3.解决了静态类爆炸问题(类的数量减少,实现了强大的功能 相对于静态而言)
缺点:
1、会出现更多的代码,更多的类,增加程序复杂性。
2、动态装饰时,多层装饰时会更复杂。
3. 排错困难
案例分享
IO流:对文件的操作 我们和对外的交互
class Data extend
装饰者模式:动态的给一个对象增加额外的职责 (装饰者模式是一种结构型设计模式,它允许你动态地给一个对象添加额外的职责。该模式通过将对象放入包装器中来实现这一点,同时保持接口整洁和向后兼容性。装饰器可以在不修改现有代码的情况下扩展对象的功能,它可以灵活地添加或删除功能,易于维护和扩展。)
动态:组合关系 继承是是它称为被装饰者 组合是让他成为装饰者
结构性设计模式:类和类的关系 A.继承 组合 动态 B.组合优于继承
静态:继承关系
第十六讲
桥接模式的学习(合成复用原则)类组合
装饰着模式有什么不同:
①装饰器Q模式是依靠一侧的类的具体实现,另一侧是抽象的,桥接模式每个角度都有具体实现。
2.语法不同 :装饰者模式实现了抽象部件(待装式)
多次装饰
桥接模式:组合(引用了另一个维度的对象) 运用场景
桥:两个维度毫无关联
装:有关联
定义:
将抽象部分和实现部分解耦, 使得能够独立的变化。
Pen Color RedColor BIgpen
Pen Color
角色
抽象部分:Pen
扩充抽象部分:BigPen
实现部分:Color
实现部分实现类:RedColor
桥接模式核心点
Color Color color pen