面试 --- java 设计模式

zz/2024/4/20 14:33:57

** 简述 设计模式 七大原则 **

1.开发封闭原则 : 对扩展开放  ,  对修改封闭。  在程序需要就行扩展的时候 , 不能去修改 原有的代码, 形成一个 热插拔 的效果。2.单一职责原则:  一个类 接口 或 方法  只负责  一个 职责  ,降低代码复杂度  以及 变更引起的风险。3.依赖倒置原则: 针对接口编程 , 依赖于 抽象类 或 接口 	而不依赖于  具体实现类。4.接口隔离原则: 将不同 功能 定义在不同接口中 实现 接口隔离。5.里氏替换原则: 任何 基类 可以出现的 地方  ,子类 都一定可以 出现。6.迪米特原则: 每个模块 都要 对 其他模块 尽可能 少地 了解 或 依赖 ,降低 代码耦合度。7.合成复用原则: 尽量 使用  组合/聚合 而不是  继承  达到 软件复用 的 目的。

** 简述 设计模式 的 分类 **

1.创建型模式: 在创建对象的 同时 隐藏 逻辑 ,不使用 new 直接 实例化对象

	有(工厂方法模式  抽象工厂模式  单例模式   建造者模式   原型模式)

2.结构型模式: 通过 类和接口 间的 继承和引用 实现 创建 复杂结构的对象。
有 (适配器模式 装饰器模式 代理模式 外观模式 桥接模式 组合模式 享元模式)

3.行为型模式: 通过 类之间 不同 的 通信方法 实现 不同行为。
有 (策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式)

** 什么 是 策略 模型 ? **
策略模型 定义了 算法族, 分别封装起来,让他们之间 可以相互 替换 ,
此模式让 算法的 变化 独立 于 使用 算法的客户。

优点 : 遵循了 开闭原则 ,扩展性好。

缺点 : 随着 策略的 增加, 对外暴露越来越多。

策略模式

例子:
出行方式如 开车,坐火车,坐飞机,可以把出行方式作为策略封装起来,可以在不改动原有的类的基础上,新增新的交通工具

使用 Compartor接口实现比较器策略,可以随意使用 任意条件进行比较排序。
如: 猫的 高度,重量。
只需要实现 Compartor接口,实现接口中的方法。
可以在不修改原有代码的基础上,对原有功能的一个扩展,符合开闭原则。

具体代码实现:
public static void main(String[] args) {
Cat[] cats={new Cat(1,1),new Cat(21,0),new Cat(3,3)};
SortCat s=new SortCat();
s.sort(cats,new CatCom());
System.out.println(Arrays.toString(cats));
}

public class Cat {
int he;
int we;

public Cat(int he, int we) {this.he = he;this.we = we;
}@Override
public String toString() {return "Cat{" +"he=" + he +", we=" + we +'}';
}

}

public class CatCom implements Comparator {
public int compare(Cat o1, Cat o2) {
if (o1.he>o2.he)
return -1;
else if (o1.he < o2.he)
return 1;
else return 0;
}
}

public class SortCat {
public void sort(T[] t, Comparator comparator) {
for (int i = 0; i < t.length; i++) {
int min = i;
for (int j = 0; j < t.length; j++) {
min = comparator.compare(t[j], t[min]) == -1 ? j : min;
}
swap(t, i, min);
}
}

public void swap(T[] arr, int i, int j) {T t = arr[i];arr[i] = arr[j];arr[j] = t;
}

以生活中的例子来说,比如我们要出去旅游,选择性很多,可以选择骑车、开车、坐飞机、坐火车等,就可以使用策略模式,把每种出行作为一种策略封装起来,后面增加了新的交通方式了,如超级高铁、火箭等,就可以不需要改动原有的类,新增交通方式即可,这样也符合软件开发的开闭原则。 策略模式实现代码如下:

/\* \* 声明旅行 \*/
interface ITrip {void going();
}
class Bike implements ITrip {@Overridepublic void going() {System.out.println("骑自行车");}
}
class Drive implements ITrip {@Overridepublic void going() {System.out.println("开车");}
}/\* \* 定义出行类 \*/
class Trip {private ITrip trip;public Trip(ITrip trip) {this.trip = trip;}public void doTrip() {this.trip.going();}
}
/\* \* 执行方法 \*/
public class StrategyTest {public static void main(String[] args) {Trip trip = new Trip(new Bike());trip.doTrip();}
}

在这里插入图片描述

public  abstract  class Duck {//接口FlyBehavior flyBehavior;QuackBehavior quackBehavior;public abstract void display();public void swim(){System.out.println("all duck float,evendecoys");}public void performFly(){flyBehavior.fly();}public void performQucak(){quackBehavior.quack();}public FlyBehavior getFlyBehavior() {return flyBehavior;}public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public QuackBehavior getQuackBehavior() {return quackBehavior;}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}
}public class MallardDuck extends Duck{@Overridepublic void display() {System.out.println("i am real Mallard duck");}public MallardDuck() {flyBehavior=new FlyWithWings();quackBehavior=new Qucak();}
}public class ModeDuck extends Duck{@Overridepublic void display() {System.out.println("i am Model duck");}public ModeDuck() {flyBehavior=new FylNoWay();quackBehavior=new Qucak();}
}public interface FlyBehavior {public void fly();
}public class FlyRockPowered implements  FlyBehavior{@Overridepublic void fly() {System.out.println("iam flying with a rocket");}
}public class FlyWithWings implements FlyBehavior{@Overridepublic void fly() {System.out.println("I can fly");}
}public class FylNoWay implements FlyBehavior{@Overridepublic void fly() {System.out.println("i am can not  fly");}
}public interface QuackBehavior {public void quack();
}public class Qucak implements QuackBehavior{@Overridepublic void quack() {System.out.println("Qucak");}
}public class MinDuckSimulator {public static void main(String[] args) {Duck duck=new MallardDuck();duck.performQucak();duck.performFly();duck.swim();duck.display();Duck model=new ModeDuck();model.performFly();model.setFlyBehavior(new FlyRockPowered());model.performFly();}
}

在这里插入图片描述


**单例模式 **

public class Singletion {
//双层检查加锁//volatile 确保 uniqueInstance 变量被初始化 成  Singletion实例时候,多个线程能正确处理 uniqueInstance 变量private volatile static Singletion uniqueInstance;private Singletion(){};public  static  Singletion getInstance(){//检查实例  如果不存在就进入同步框块if(uniqueInstance == null){//只有第一次才彻底执行这里synchronized(Singletion.class){//进入区块后,再检查一次,如果还是null,才创建实例if(uniqueInstance ==null){//进入区块后,再检查一次,如果还是null,才创建实例uniqueInstance=new Singletion();}}}return  uniqueInstance;}}

单例模式 确保程序中 一个类 最多只有一个实例。
单例模式 也提供 访问 这个实例的 全局点。
在java 中 实现单例模式 需要私有构造器 ,一个静态方法和静态变量
确定性能和资源上的限制 ,然后小心选择适当的 方式 实现 单例模式,以解决多线程问题。

在这里插入图片描述
** 实现一:立即加载 / “饿汉模式” **

立即加载就是使用类的时候已经将对象创建完毕(不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故又被称为“饿汉模式”),常见的实现办法就是直接new实例化。

	public class Singleton {// 将自身实例化对象设置为一个属性,并用static、final修饰private static final Singleton instance = new Singleton();// 构造方法私有化private Singleton() {}// 静态方法返回该实例public static Singleton getInstance() {return instance;}
}

饿汉模式”的优缺点:

优点:实现起来简单,没有多线程同步问题。

缺点:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。


** 实现二:延迟加载 / “懒汉模式” **

延迟加载就是调用get()方法时实例才被创建(先不急着实例化出对象,等要用的时候才给你创建出来。不着急,故又称为“懒汉模式”),常见的实现方法就是在get方法中进行new实例化。

public class Singleton {// 将自身实例化对象设置为一个属性,并用static修饰private static Singleton instance;// 构造方法私有化private Singleton() {}// 静态方法返回该实例public static Singleton getInstance() {if(instance == null) {instance = new Singleton();}return instance;}
}

“懒汉模式”的优缺点:

优点:实现起来比较简单,当类SingletonTest被加载的时候,静态变量static的instance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,因此在某些特定条件下会节约了内存。

缺点:在多线程环境中,这种实现方法是完全错误的,根本不能保证单例的状态。


** 实现三:线程安全的“懒汉模式” **

public class Singleton {// 将自身实例化对象设置为一个属性,并用static修饰private static Singleton instance;// 构造方法私有化private Singleton() {}// 静态方法返回该实例,加synchronized关键字实现同步public static synchronized Singleton getInstance() {if(instance == null) {instance = new Singleton();}return instance;}
}

在这里插入图片描述

优点:在多线程情形下,保证了“懒汉模式”的线程安全。

缺点:众所周知在多线程情形下,synchronized方法通常效率低,显然这不是最佳的实现方案。


** 代理模式**

代理模式— 为另一个对象 提供 一个 替身 或 占位符 以 访问 这个对象。

使用代理模式 创建 代表 ,让 代表对象 控制 某对象的访问, 被代理对象
可以是 远程的对象 ,创建 开销大 的 对象 或 需要安全控制的对象。


静态代理 :要求被代理类和代理类同时实现相应的一套接口,通过代理类调用重写接口的方法,实际上调用的是原始对象的同样的方法。

*静态代理实现步骤:

  • 定义一个接口及其实现类;
  • 创建一个代理类同样实现这个接口
  • 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。
1.定义发送短信的接口
package Poxy.jintai;public interface SsmService {String send(String name);
}2.实现发送短信的接口
package Poxy.jintai;public class SsmServiceImpl implements SsmService{@Overridepublic String send(String message) {System.out.println("send message: "+message);return message;}
}3.创建代理类并同样实现发送短信的接口
package Poxy.jintai;public class SsmPoxy {private final SsmService ssmService;public SsmPoxy(SsmService ssmService) {this.ssmService = ssmService;}public String send(String message){//调用方法之前,我们可以添加自己的操作System.out.println("before method send()");ssmService.send(message);//调用方法之后,我们同样可以添加自己的操作System.out.println("after method send()");return null;}}4.实际使用
package Poxy.jintai;public class PoxyMain {public static void main(String[] args) {SsmService ssmService=new SsmServiceImpl();SsmPoxy ssmPoxy=new SsmPoxy(ssmService);ssmPoxy.send("java");}
}5.运行上述代码之后,控制台打印出:
before method send()
send message: java
after method send()

总结:
可以输出结果看出,我们已经增加了 SmsServiceImpl 的send()方法。


动态代理 : 在运行时 动态地 创建 一个代理类 , 实现一个或 多个 接口,并将 方法的 调用 转发到 你 指定的类

从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心

Proxy 类中使用频率最高的方法是:newProxyInstance() ,这个方法主要用来生成一个代理对象。

public static Object newProxyInstance
(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{......}loader :类加载器,用于加载代理对象。
interfaces : 被代理类实现的一些接口;
h : 实现了 InvocationHandler 接口的对象;

要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。
当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。

public interface InvocationHandler {/*** 当你使用代理对象调用方法的时候实际会调用到这个方法*/
public Object invoke
(Object proxy, Method method, Object[] args)throws Throwable;
}proxy :动态生成的代理类
method : 与代理类对象调用的方法相对应
args : 当前 method 方法的参数

通过Proxy 类的 newProxyInstance() 创建的代理对象在调用方法的时候,实际会调用到实现InvocationHandler 接口的类的 invoke()方法。

可以在 invoke() 方法中自定义处理逻辑,比如在方法执行前后做什么事情。

*JDK 动态代理类使用步骤

  • 定义一个接口及其实现类
  • 自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑
  • 通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象
定义发送短信的接口
package Poxy.dongtai;public interface SsmService {String send(String name);
}实现发送短信的接口
package Poxy.dongtai;public class SsmServiceImpl implements SsmService {@Overridepublic String send(String message) {System.out.println("send message: "+message);return message;}
}定义一个 JDK 动态代理类
package Poxy.dongtai;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** JDK 动态代理类*/
public class DebugInvocationHandler implements InvocationHandler {/*** 代理类中的真实对象*/private final Object target;public DebugInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Exception {//调用方法之前,我们可以添加自己的操作System.out.println("before method " + method.getName());Object result = method.invoke(target, args);//调用方法之后,我们同样可以添加自己的操作System.out.println("after method " + method.getName());return result;}
}获取代理对象的工厂类
package Poxy.dongtai;import java.lang.reflect.Proxy;/*** 获取代理对象的工厂类*/
public class JdkProxyFactory {public static Object getProxy(Object target){return Proxy.newProxyInstance(target.getClass().getClassLoader(), //目标类 的 类加载target.getClass().getInterfaces(),  //代理需要 实现的接口 可指定多个new DebugInvocationHandler(target)  // 代理对象 对应的自定义  InvocationHandler);}
}实际使用
package Poxy.dongtai;public class DongTaiMain {public static void main(String[] args) {SsmService ssmService= (SsmService) JdkProxyFactory.getProxy(new SsmServiceImpl());ssmService.send("java");}
}运行上述代码之后,控制台打印出:
before method send
send message: java
after method send

JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类


*CGLIB 动态代理机制
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB 通过继承方式实现代理。很多知名的开源框架都使用到了CGLIB, 例如 Spring 中的 AOP 模块中:如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。

在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。

你需要自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法。

public interface MethodInterceptor
extends Callback{// 拦截被代理类中的方法public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
}
obj :被代理的对象(需要增强的对象)
method :被拦截的方法(需要增强的方法)
args :方法入参
proxy :用于调用原始方法

可以通过 Enhancer类来动态获取被代理类,当代理类调用方法的时候,实际调用的是 MethodInterceptor 中的 intercept 方法

*CGLIB 动态代理类使用步骤

  • 定义一个类
  • 自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,和 JDK 动态代理中的 invoke 方法类似
  • 通过 Enhancer 类的 create()创建代理类

不同于 JDK 动态代理不需要额外的依赖。CGLIB(Code Generation Library) 实际是属于一个开源项目,如果你要使用它的话,需要手动添加相关依赖

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
实现一个使用阿里云发送短信的类
package github.javaguide.dynamicProxy.cglibDynamicProxy;public class AliSmsService {public String send(String message) {System.out.println("send message:" + message);return message;}
}自定义 MethodInterceptor(方法拦截器)
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 自定义MethodInterceptor*/
public class DebugMethodInterceptor implements MethodInterceptor {/*** @param o           代理对象(增强的对象)* @param method      被拦截的方法(需要增强的方法)* @param args        方法入参* @param methodProxy 用于调用原始方法*/@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//调用方法之前,我们可以添加自己的操作System.out.println("before method " + method.getName());Object object = methodProxy.invokeSuper(o, args);//调用方法之后,我们同样可以添加自己的操作System.out.println("after method " + method.getName());return object;}}获取代理类
import net.sf.cglib.proxy.Enhancer;public class CglibProxyFactory {public static Object getProxy(Class<?> clazz) {// 创建动态代理增强类Enhancer enhancer = new Enhancer();// 设置类加载器enhancer.setClassLoader(clazz.getClassLoader());// 设置被代理类enhancer.setSuperclass(clazz);// 设置方法拦截器enhancer.setCallback(new DebugMethodInterceptor());// 创建代理类return enhancer.create();}
}实际使用
AliSmsService aliSmsService = (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
aliSmsService.send("java");
运行上述代码之后,控制台打印出:
before method send
send message:java
after method send

*JDK 动态代理和 CGLIB 动态代理对比

JDK 动态代理只能代理实现了接口的类或者直接代理接口,
而 CGLIB 可以代理未实现任何接口的类。

CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。

就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。


*静态代理和动态代理的对比

灵活性 :动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的!

JVM 层面 :静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。


保护代理:这是一种根据访问权限 决定 客户可否 访问对象的代理。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


观察者模式

出版者+订阅者 = 观察者模式

观察者模式:

定义了 对象之间的 一对多依赖, 这样一来,当一个对象改变状态时,它的 所有依赖者 都会 收到 通知 并 自动更新

观察者模式 定义了 一系列 对象之间 的 一对多关系

当一个对象改变状态, 其他依赖者 都会收到 通知

松耦合
当两个对象之间松耦合, 它们依然可以 交互 , 但是不太清楚彼此的细节

观察者模式提供了 一种 设计对象, 让 主题和观察者 之间 松耦合

主题(可观察者)用一个 共同的接口 来更新观察者

使用观察者模式 可以从 被观察者 推(push) 或者 拉(pull) 数据

有多个观察者时, 不可以 依赖特定的通知次序

SWing 使用了大量 观察者模式,
在这里插入图片描述

package guangchazhe;
//主题接口
public interface Subject {//这两个方法都需要一个 观察者作为变量 该观察者用于 注册和删除public void registerObserver(Observer o);public void removeObserver(Observer o);//当主题状态改变时候,用于通知所有观察者public void notifyObservers();//所有观察者都需要 实现 update()方法, 以实现 观察者接口public interface Observer{//当气象观测值改变时, 主题会把这些状态值当做方法的参数 传递给观察者public void  update(float temp,float humidity,float perssure);}//当布告栏需要显示的时候 调用此方法public  interface DisplayElement{public void display();}
}
package guangchazhe;//布告栏
public class CurrentConditionsDisplay implements Subject.Observer, Subject.DisplayElement {private float temperature;private float humidity;private Subject weatherData;public CurrentConditionsDisplay(Subject weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}public void update(float temp, float humidity, float perssure) {this.temperature=temp;this.humidity=humidity;display();}@Overridepublic void display() {float t = temperature;float rh = humidity;float heatIndex = (float)((16.923 + (0.185212 * t)) +(5.37941 * rh) -(0.100254 * t * rh) +(0.00941695 * (t * t)) +(0.00728898 * (rh * rh)) +(0.000345372 * (t * t * rh)) -(0.000814971 * (t * rh * rh)) +(0.0000102102 * (t * t * rh * rh)) -(0.000038646 * (t * t * t)) +(0.0000291583 * (rh * rh * rh)) +(0.00000142721 * (t * t * t * rh)) +(0.000000197483 * (t * rh * rh * rh)) -(0.0000000218429 * (t * t * t * rh * rh)) +(0.000000000843296 * (t * t * rh * rh * rh)) -(0.0000000000481975 * (t * t * t * rh * rh * rh)));System.out.println(temperature +":"+humidity+":");System.out.println(heatIndex);}
}
package guangchazhe;import java.util.ArrayList;//在这个类中 实现主题接口
public class WeatherData implements Subject {private ArrayList obsevers;private float temperature;private float humidity;private float pressure;public WeatherData(){obsevers=new ArrayList();}//注册public void registerObserver(Observer o) {obsevers.add(o);}//取消注册public void removeObserver(Observer o) {final int i = obsevers.indexOf(o);if (i >=0){obsevers.remove(i);}}//通知public void notifyObservers() {//把状态通知到了所有的订阅者for (int i = 0; i < obsevers.size(); i++) {Observer observer= (Observer) obsevers.get(i);observer.update(temperature,humidity,pressure);}}//当获取到最新值通知 观察者public void measuresChange(){notifyObservers();}public void setMeasures(float temperature,float humidity,float pressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measuresChange();}public static void main(String[] args) {WeatherData weatherData=new WeatherData();CurrentConditionsDisplay conditionsDisplay=new CurrentConditionsDisplay(weatherData);weatherData.setMeasures(60,65,30.4f);weatherData.setMeasures(160,165,130.4f);weatherData.setMeasures(260,265,130.4f);}
}

java自带API

package guangchazhe.api;import guangchazhe.Subject;import java.util.Observable;
import java.util.Observer;//布告栏
public class CurrentConditionsDisplay implements Observer, Subject.DisplayElement {private float temperature;private float humidity;private Observable observable;public CurrentConditionsDisplay(Observable observable) {this.observable = observable;//注册observable.addObserver(this);}@Overridepublic void update(Observable o, Object arg) {if (o instanceof  WeatherData){WeatherData weatherData= (WeatherData) o;this.temperature=weatherData.getTemperature();this.humidity=weatherData.getHumidity();display();}}@Overridepublic void display() {float t = temperature;float rh = humidity;float heatIndex = (float)((16.923 + (0.185212 * t)) +(5.37941 * rh) -(0.100254 * t * rh) +(0.00941695 * (t * t)) +(0.00728898 * (rh * rh)) +(0.000345372 * (t * t * rh)) -(0.000814971 * (t * rh * rh)) +(0.0000102102 * (t * t * rh * rh)) -(0.000038646 * (t * t * t)) +(0.0000291583 * (rh * rh * rh)) +(0.00000142721 * (t * t * t * rh)) +(0.000000197483 * (t * rh * rh * rh)) -(0.0000000218429 * (t * t * t * rh * rh)) +(0.000000000843296 * (t * t * rh * rh * rh)) -(0.0000000000481975 * (t * t * t * rh * rh * rh)));System.out.println("javaAPI");System.out.println(temperature +":"+humidity+":");System.out.println(heatIndex);}}package guangchazhe.api;import java.util.Observable;//在这个类中 实现主题接口
public class WeatherData extends Observable {private float temperature;private float humidity;private float pressure;public WeatherData(){}//当获取到最新值通知 观察者public void measuresChange(){//指示状态已经改变setChanged();notifyObservers();}public void setMeasures(float temperature,float humidity,float pressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measuresChange();}public float getTemperature() {return temperature;}public float getHumidity() {return humidity;}public float getPressure() {return pressure;}public static void main(String[] args) {WeatherData weatherData=new WeatherData();CurrentConditionsDisplay conditionsDisplay=new CurrentConditionsDisplay(weatherData);// weatherData.deleteObserver(conditionsDisplay);weatherData.setMeasures(60,65,30.4f);weatherData.setMeasures(160,165,130.4f);weatherData.setMeasures(260,265,130.4f);}
}

**装饰者模式 **

含义: 动态地 将 责任 附加到 对象上, 想要 扩展 功能 ,装饰者 提供 有别于 继承的 另一种选择,
要点:
在这里插入图片描述

示例 :
实现 装饰者模式中 -咖啡

package 装饰者模式.Coffe;/*** date 2021/11/721:42** @author mzr* @target :实现 装饰者模式中  -咖啡**/
// Beverage 是一个 抽象类 ,有 两个方法 getDescip() 和 cost()
public abstract class Beverage {String desciption="Unknow Beverage";public String getDesciption(){return desciption;}public abstract double cost();//装饰类public abstract static class CondimentDecorator extends Beverage{public abstract String getDesciption();}//饮料//Espressopublic static class Espresso extends  Beverage{public Espresso(){desciption="Espresso";}public double cost() {return 1.99;}}//饮料//DaikRoastpublic static class DaikRoast extends Beverage{public DaikRoast(){desciption="DaikRoast";}public double cost() {return 0.89;}}//饮料//HouseBlendpublic class HouseBlend extends Beverage{public HouseBlend(){desciption="HouseBlend";}public double cost() {return 0.89;}}//调料public static class Mocha extends CondimentDecorator{Beverage beverage;public Mocha(Beverage beverage){this.beverage=beverage;}@Overridepublic double cost() {return 0.20+beverage.cost();}@Overridepublic String getDesciption() {return beverage.getDesciption()+" ,Mocha";}}//调料public static class Whip extends CondimentDecorator{Beverage beverage;public Whip(Beverage beverage){this.beverage=beverage;}@Overridepublic double cost() {return 0.30+beverage.cost();}@Overridepublic String getDesciption() {return beverage.getDesciption()+" ,Whip";}}//调料public static class Soy extends CondimentDecorator{Beverage beverage;public Soy(Beverage beverage){this.beverage=beverage;}@Overridepublic double cost() {return 0.40+beverage.cost();}@Overridepublic String getDesciption() {return beverage.getDesciption()+" ,Soy";}}
}

主方法

package 装饰者模式.Coffe;/*** date 2021/11/721:56** @author mzr* @target : 主方法**/
public class StarbuzzCoffe {public static void main(String[] args) {Beverage beverage=new Beverage.Espresso();System.out.println(beverage.getDesciption() +"$"+beverage.cost());Beverage beverage2=new Beverage.DaikRoast();beverage2=new Beverage.Mocha(beverage2);beverage2=new Beverage.Whip(beverage2);beverage2=new Beverage.Mocha(beverage2);System.out.println(beverage2.getDesciption() +"$"+beverage2.cost());Beverage beverage3=new Beverage.DaikRoast();beverage3=new Beverage.Mocha(beverage3);beverage3=new Beverage.Whip(beverage3);beverage3=new Beverage.Soy(beverage3);System.out.println(beverage3.getDesciption() +"$"+beverage3.cost());}
}
Espresso$1.99
DaikRoast ,Mocha ,Whip ,Mocha$1.59
DaikRoast ,Mocha ,Whip ,Soy$1.79

编写自己的 IO 装饰者

package 装饰者模式.IO;import java.io.*;
import java.nio.charset.Charset;/*** date 2021/11/722:05** @author mzr* @target :编写自己的 IO 装饰者**/
public class LowerCaseInputStream extends FilterInputStream {protected LowerCaseInputStream(InputStream in) {super(in);}@Overridepublic int read() throws IOException {int c= super.read();return (c == -1 ? c : Character.toLowerCase(c));}@Overridepublic int read(byte[] b, int off, int len) throws IOException {int reslut=super.read(b, off, len);for (int i = off; i <off+reslut ; i++) {b[i]= (byte) Character.toLowerCase(b[i]);}return reslut;}public static void main(String[] args) {int c;try {InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));while ( (c = in.read()) >=0){System.out.println(c);}}catch (IOException e){e.printStackTrace();}}
}

工厂模式

抽象工厂模式 — 提供一个 接口 , 用于 创建 相关 或 依赖的 家族, 而不需要 明确 指定 具体类

工厂方法模式 — 定义了 一个 创建 对象的 接口 , 但由于 类 决定 要 实例化 是 哪一个 。

工厂 方法让 类 把 实例化 推迟 到 子类

在这里插入图片描述


http://www.ngui.cc/zz/2336530.html

相关文章

springboot+dubbo实现项目itrip-search-consumer流程

准备 把3个solr的工具类&#xff08;BaseQuery、Param、SolrParam&#xff09;放到itrip-common中&#xff0c;导如下依赖&#xff1a; <!--solr导这个包&#xff0c;注意版本号为2.1.1--><dependency><groupId>org.springframework.data</groupId>&…

自恢复保险丝的各个参数含义

在项目中发现&#xff1a;自恢复保险丝存在一定的压差&#xff0c;这在一些电源要求较高的环境下要慎重选择。 自恢复保险丝工作原理 当有异常过电流通过自恢复保险丝时&#xff0c;产生的热量使高分子有机聚合物膨胀&#xff0c;包裹在高分子有机聚合物的导电粒子会分开&…

如何使用Java来发送企业邮箱,并设计收到邮件的样式

最近再给公司写一个发送邮件的系统&#xff0c;收到同事反馈说收到的默认样式太丑了&#xff0c;于是我钻研了一下&#xff0c;设计了一下自己的邮箱前端样式&#xff0c;于是特此写下这篇文章 一.搭建环境 相信大家也在其余的博客中学习到了怎么使用qq邮箱来发送邮件&#xff…

java入门-springboot+mybatis+vue实现简单的后台管理系统

源码地址:https://codechina.csdn.net/wwwzhouzy/vueadmin 注意:前后端在一个地址&#xff0c;vueClient是vue前端&#xff0c;zhouzyServer是后端 一、效果图 1、列表 2、图表 二、代码 此处贴核心代码 后端 代码结构&#xff1a; 1、pom引包 因为我用的是mysql5.0&…

CentOS7 搭建 iSCSI网络存储

服务器端安装配置//安装iscsi服务 #yum -y install targetcli//创建目录以便于设置共享 #mkdir /iscsi_iso//进入进入管理控制台 #targetcli /> cd backstores/fileio /backstores/fileio> create iso /iscsi_iso/iso.img 2G Created fileio iso with size 214748364…

Redis分布式锁入门

一.分布式锁是什么 首先&#xff0c;我们得知道&#xff0c;锁可以分为三种 线程锁&#xff1a;主要用来给方法、代码块加锁。当某个方法或代码使用锁&#xff0c;在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果&#xff0c;因为线程锁的实现在根本上…

ubuntu下ice的安装和使用

安装命令&#xff1a;sudo apt-get install ice33-*事情是这样的&#xff0c;刚开始我是网上搜了一下&#xff0c;别人说sudo apt-get install ice33-translators即可&#xff0c;但是在我实践了一下&#xff0c;只安装这个ice33-translators在接下来的操作中连编译都过不了。因…

linux下如何启动ice服务器,Linux下ICE的安装

ICE在Linux下的完整编译安装安装平台要求&#xff1a;最好用gcc 4.x版编译ICE&#xff0c;在Slackware下发现gcc3.3.6和gcc3.4.6都无法编译通过为了方便管理&#xff0c;将ICE相关的软件都安装到/usr/local/ICE-3.3.0/目录下首先 安装第三方包&#xff1a;ThirdParty-Sources-3…

linux编译ice,linux环境下编译安装ICE

前面我们讲过了在linux环境下通过rpm的方式来安装ICE&#xff0c;这种安装方式可以是比较简单的&#xff0c;自己在安装过程中发现后面PHP无法装在IcePHP.sp模块&#xff0c;也有可能自己在安装过程中某个地方出错了。又尝试通过直接编译的方式去安装ICE&#xff0c;PHP也正常装…

IceE研究之一 shared和handle

IceE简介 ICE 是指ZeroC公司的ICE&#xff08;Internet Communications Engine&#xff09;中件间。对于客户端和服务端程序的开发提供了很大的便利。而IceE则是ICE的嵌入式版&#xff0c;在ICE的基础上进行了裁剪。 一、shared shared在Shared.h中定义。它的作用是提供一个引…