什么是设计模式? 设计模式是一种可重复使用的解决方案。软件开发的祖先将总结开发过程中遇到的问题,并给出解决方案。当年轻一代遇到类似的问题时,他们可以使用这些解决方案来解决问题。(从设计模式可以看出,祖先对接口的应用。
? 单例模式(ps:参考https://www.cnblogs.com/xiaofengwang/p/11255678.html) 一类只有一个实例对象。这个对象的构造器是private所以不能在其他地方修改new,只能通过getInstance()获取实例。 单例模式的几种写法(还有其他的写法): ○ 懒汉风格(加上synchronized 线程安全的关键字。
1 public class Singleton 2 { 3 private static Singleton instance; 4 private Singleton(){} 5 public static synchronized Singleton getInstance(){ 6 if(instance == null){ 7 instance = new Singleton(); 8 } 9 return instance; 10 } 11 }
○ 饿汉式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } }
○ 双检查锁(不仅可以避免线程安全问题,还可以防止反序列化重建对象。
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
? 观察者模式: 观察者设计模式定义了一对多的关系。一个对象 A 与多个对象 B、C、D 建立观察与观察关系。当对象 A 当状态发生变化时,将通知所有观察者 B、 C、 D。当B、C、D 在接收到 A 状态变更通知后,根据自身实际情况做出相应变更。通常观察者和观察者都是接口,上述对象是指实现这些接口的对象。
观察者接口:
package com.bzw.observer; public interface Observer { ///接到通知后,应具体处理 void handleNotify(String message); }
观察者接口:
package com.bzw.observer; public interface ToBeObservered { public void addObserver(Observer observer); public void removeObserver(Observer observer); public void notifyObserver(String message); }
创建观察者:
package com.bzw.observer; public class ObserverA implements Observer{ @Override public void handleNotify(String message) { System.out.println(message "A正在处理通知"); } } package com.bzw.observer; public class ObserverB implements Observer{ @Override public void handleNotify(String message) { System.out.println(message "B正在处理通知"); } }
创建被观察者:
package com.bzw.observer; import java.util.ArrayList; import java.util.List; public class Observered implements ToBeObservered{ List<Observer> observers = new ArrayList<>(); @Override public void addObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObserver(String message) { for(Observer o : observers) { o.handleNotify(message); } } }
测试类:
package com.bzw.observer; public class ObserverTest { public static void main(String args[]) { ObserverA xiaowang = new ObserverA(); ObserverB xiaoli = new ObserverB(); Observered beauty = new Observered(); beauty.addObserver(xiaowang); beauty.addObserver(xiaoli); beauty.notifyObserver("快来呀"); // System.out.println("----------------------"); // beauty.removeObserver(xiaoli); // beauty.notifyObserver("再来呀"); } }
? 装饰者模式 在扩展对象功能时,可以考虑装饰模式。 优点:无需修改被修改对象的源代码,装饰者与被装饰者耦合度不高。
package com.bzw.decorate; /** * * 面条装饰器 * */ public interface NoodleDecorate { public void addThings(); }
package com.bzw.decorate;
public class Noodle implements NoodleDecorate{
/**
* 普通拉面
*/
@Override
public void addThings() {
System.out.println("两片牛肉");
System.out.println("一根胡萝卜");
System.out.println("三根香菜");
}
}
package com.bzw.decorate;
public class ChiliNoodle implements NoodleDecorate{
private Noodle noodle;
//将普通拉面对象传入
public ChiliNoodle(Noodle noodle) {
this.noodle = noodle;
}
@Override
//对普通拉面进行修饰
public void addThings() {
noodle.addThings();
System.out.println("加三勺辣椒");
}
}
测试类:
package com.bzw.decorate;
public class NoodleTest {
public static void main(String args[]) {
Noodle noodle = new Noodle();
ChiliNoodle cn = new ChiliNoodle(noodle);
cn.addThings();
}
}
• 适配器模式(ps :参考https://www.cnblogs.com/luohanguo/p/10334291.html) 可以让原本接口不一致的类可以一起工作。有三种方式:类的适配器模式,对象适配器模式,接口适配器模式。其中对象适配器模式和接口适配器模式可以较小程度的修改源码,代码耦合度低。当不希望实现接口中的所有方法时,可以用接口适配器模式,其他情况建议用对象适配器模式。
第一种方式:
package com.bzw.adapter;
public class Phone {
public void typecPhone() {
System.out.println("信息从typec口的手机输入。");
}
}
package com.bzw.adapter;
public interface Vga {
void vgaInterface();
}
package com.bzw.adapter;
/*
* 适配器第一种方式:类的适配器模式
*/
public class TypecVga1 extends Phone implements Vga{
@Override
public void vgaInterface() {
typecPhone();
System.out.println("接收到typec口信息,转到vga接口中....");
System.out.println("信息已转成vga,可以与显示屏对接");
}
}
第二种方式: Phone类和Vga接口和方式一一样。
package com.bzw.adapter;
/*
* 第二种方式:对象适配器模式
*/
public class TypecVga2 implements Vga{
private Phone phone;
public TypecVga2(Phone phone) {
this.phone = phone;
}
@Override
public void vgaInterface() {
if(phone != null) {
phone.typecPhone();
System.out.println("接收到typec口信息,转到vga接口中....");
System.out.println("信息已转成vga,可以与显示屏对接");
}
}
}
测试类:
package com.bzw.adapter;
public class Screen {
public static void main(String args[]) {
System.out.println("----------第一种方式-------------");
TypecVga1 adapter1 = new TypecVga1();
adapter1.vgaInterface();
System.out.println("----------显示屏与适配器连接,手机成功投影到显示器------------");
System.out.println("\n");
System.out.println("----------第二种方式--------------");
Phone phone = new Phone();
TypecVga2 adapter2 = new TypecVga2(phone);
adapter2.vgaInterface();
System.out.println("----------显示屏与适配器连接,手机成功投影到显示器------------");
}
}
第三种方式:
package com.bzw.adapter.TypecVga3;
/*
* 第三种方式:接口的适配器模式
*/
//在这个接口中可以定义多个抽象方法。
public interface Target {
public void typec();
public void typecVga();
public void typecHdmi();
}
package com.bzw.adapter.TypecVga3;
//抽象类实现接口中的所有方法,这样就意味着抽象方法被实现了,子类在继承时, //可以有选择性的重写。
public abstract class Adapter implements Target{
public void typec() {};
public void typecVga() {};
public void typecHdmi() {};
}
package com.bzw.adapter.TypecVga3;
public class VgaAdapter extends Adapter{
public void typec() {
System.out.println("信息从typec口的手机输入。");
}
public void typecVga() {
System.out.println("接收到typec口信息,转到vga接口中....");
System.out.println("信息已转成vga,可以与显示屏对接");
}
/**可以根据需要选择要重写的方法。
public void typecHdmi() {
System.out.println("接收到typec口信息,转到HDMI接口中....");
System.out.println("信息已转成HDMI,可以与显示屏对接");
}*/
}
测试类:
package com.bzw.adapter.TypecVga3;
public class Screen {
public static void main(String arg[]) {
System.out.println("---------第三种方式----------------");
VgaAdapter adapter3 = new VgaAdapter();
adapter3.typec();
adapter3.typecVga();
System.out.println("----------显示屏与适配器连接,手机成功投影到显示器------------");
}
}
• 代理模式 为一个对象提供一个代理以控制外界对该对象的访问。 ○ 静态代理:代理类和相关方法直接在代码中写死。 ○ 动态代理:可以直接给某一个目标对象生成一个代理对象,二不需要代理类的存在。 代理模式的优点: ○ 提高程序的扩展性和可复用性。(动态代理) ○ 保护对象。
• 工厂模式 用工厂提供的方法代替使用new创建对象的操作,将创建对象统一管理和控制从而将调用者与实现类进行解耦,实现创建者与调用者的分离。 实现工厂模式的三种方式: ○ 简单工厂模式(静态工厂):实际上它并不算是设计模式,只不过算是工厂方法和抽象工厂的基础,不过也有一些运用的地方。比如jdk的动态代理的Proxy.newProxyInstance这个就是一个简单工厂。 ○ 工厂方法:工厂方法模式的实质是定义一个用于创建对象的接口,然后让实现这个接口的类来决定创建哪个类的对象。 ○ 抽象工厂:抽象工厂模式提供了一种方式,可以将同一产品族的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。
对象适配器模式是其他6种结构型设计模式的起源。
三种方式总结: ○ 静态工厂 : 用来生产同一等级结构中的任意产品。产品的创建是由你传入参数决定的。 ○ 工厂方法 :用来生产同一等级结构中的固定产品。一个工厂只能生产一个固定的产品。 ○ 抽象工厂 :用来生产不同产品族的全部产品。一个工厂可以生产跟该产品相关的一系列产品。