Java设计模式(1)
单例模式
实现单例模式主要有如下几个关键点:
- 构造函数不对外开放,一般为Private;
- 通过一个静态类方法或者枚举返回单例类对象;
- 确保单例类的对象有且只有一个,尤其是在多线程环境下;
- 确保单例类对象在反序列化时不会重新构造对象。
单例模式构造的类对于程序而言,就像独生子女对于家庭。
观察者模式
观察者模式又称为发布/订阅(Publish/Subscribe)模式,在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
里面存在核心角色:
抽象被观察者角色:
也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:
为所有的具体观察者定义一个接口,在得到主题通知是更新自己。
具体被观察者角色:
也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:
实现抽象观察者角色所需要的更新接口,一边使本事
被观察者改变时,依次调用依赖于它的观察者中的方法,是观察者也改变。
运用场景:
- 多人聊天室,服务器就是被观察者,用户的客户端就是观察者
- 网游,服务器将客户端的状态进行分发
- Android中的广播机制
- 社交平台的关注推送
建造者模式
建造者模式,顾名思义,在实例化的时候,就需要我们一点点的去建造,去完善所需要的对象。
下面是我在网络请求中使用建造者模式构建请求体的的一个例子:
public class Request {
private String url;
private String method;
private Map<String, Object> hashMap;
private Request(String url, String method, Map<String, Object> hashMap) {
this.url = url;
this.method = method;
this.hashMap = hashMap;
}
public Map<String, Object> getHashMap() {
return hashMap;
}
public String getMethod() {
return method;
}
public String getUrl() {
return url;
}
public static class Builder {
private String url = null;
private String method = "GET";
private Map<String, Object> hashMap = null;
public Builder() {}
public Builder url(String url) {
this.url = url;
return this;
}
public Builder method(String method) {
this.method = method;
return this;
}
public Builder hashMap(Map<String, Object> hashMap) {
this.hashMap = hashMap;
return this;
}
public Request build() {
return new Request(url, method, hashMap);
}
}
}
在实例化对象时:
Request request = new Request.Builder()
.url(url)
.hashMap(postDate)
.method("POST")
.build();
适配器模式
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
说的通俗点:把一个已有的对象接到不匹配的接口上
实际应用中接触的最多的是RecyclerView
的setAdapter()
/**
* Set a new adapter to provide child views on demand.
* <p>
* When adapter is changed, all existing views are recycled back to the pool. If the pool has
* only one adapter, it will be cleared.
*
* @param adapter The new adapter to set, or null to set no adapter.
* @see #swapAdapter(Adapter, boolean)
*/
public void setAdapter(@Nullable Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
processDataSetCompletelyChanged(false);
requestLayout();
}
这里的Adapter
是RecyclerView
里面定义的,但是在编辑代码的时候,Adapter
是自己新建的一个类,叫做xxxAdapter
,这个类的实例化对象是不能直接当作参数传入setAdapter()
的,所以我们需要继承RecyclerView.Adapter<xxxAdapter.ViewHolder>
这个一个抽象,使得我们的Adapter
能够无阻碍地当作正确的参数传入。
抽象工厂模式
抽象工厂模式特别适合于这样的一种产品结构:产品分为几个系列,在每个系列中,产品的布局都是类似的,在一个系列中某个位置的产品,在另一个系列中一定有一个对应的产品。这样的产品结构是存在的,这几个系列中同一位置的产品可能是互斥的,它们是针对不同客户的解决方案,每个客户都只选择其一。
就好比如:你在购买外设的时候,可能会购买多个键盘,多个鼠标和多个耳机,你在使用的时候,任意时刻你只会使用一副键盘,一个鼠标,一个耳机。
用代码如何实现呢:
抽象的部分(接口)
// 抽象的键盘
interface Keyboard {
public String getKeyboardName();
}
// 抽象的鼠标
interface Mouse {
public String getMouseName();
}
// 抽象的耳机
interface Headset {
public String getHeadsetName();
}
// 抽象的外设(工厂)
interface Peripherals {
public Keyboard getKeyboard();
public Mouse getMouse();
public Headset getHeadset();
}
具体的键盘,鼠标,耳机
class RazerK implements Keyboard {
@Override
public String getKeyboardName() {
return "雷蛇键盘";
}
}
class RazerM implements Mouse {
@Override
public String getMouseName() {
return "雷蛇鼠标";
}
}
class RazerH implements Headset {
@Override
public String getHeadsetName() {
return "雷蛇耳机";
}
}
class LogitechK implements Keyboard {
@Override
public String getKeyboardName() {
return "罗技键盘";
}
}
class LogitechM implements Mouse {
@Override
public String getMouseName() {
return "罗技鼠标";
}
}
class LogitechH implements Headset {
@Override
public String getHeadsetName() {
return "罗技耳机";
}
}
实现装配
class PeripheralsInUse implements Peripherals {
@Override
public Keyboard getKeyboard() {
return new RazerK();
}
@Override
public Mouse getMouse() {
return new LogitechM();
}
@Override
public Headset getHeadset() {
return new RazerH();
}
}
public class Mystate {
public static void main(String[] args) {
System.out.println("我现在的状态");
state(new PeripheralsInUse());
}
private static void state(Peripherals p) {
System.out.println(p.getKeyboard().getKeyboardName());
System.out.println(p.getMouse().getMouseName());
System.out.println(p.getHeadset().getHeadsetName());
}
}
运行结果:
我现在的状态
雷蛇键盘
罗技鼠标
雷蛇耳机
责任链模式
职责链模式:避免将一个请求的发送者和请求的处理者耦合在一起,让多个对象都有处理请求的机会。将接受请求的对象连成一条线链并且沿着这条链传递请求,直到有一个对象能够处理它为止。
举个栗子,烂大街的例子😜😜😜:
公司请假,不同等级的管理能够批准的假期天数不同:
基层员工不能擅自离岗
组长可以批假半天(t <= 0.5)
项目负责人可以批假一天(t <= 1)
经理可以批假三天(t <= 3)
老板可以批假三天以上的(t > 3)
抽象的Handler
abstract class Handler {
protected Handler successor;
public abstract void handleRequest(double t);
public Handler getSuccessor(){
return successor;
}
public void setSuccessor(Handler successor){
this.successor = successor;
}
}
具体的Handler
class Boss extends Handler {
@Override
public void handleRequest(double t) {
if (t > 3) {
System.out.println("老板:我允许你请假" + t + "天");
} else {
System.out.println("老板:我很忙欸!!!");
}
}
}
class Manager extends Handler {
@Override
public void handleRequest(double t) {
if (t <= 3) {
System.out.println("经理:我允许你请假" + t + "天");
} else {
System.out.println("经理:你去问问老板");
getSuccessor().handleRequest(t);
}
}
}
class Head extends Handler {
@Override
public void handleRequest(double t) {
if (t <= 1) {
System.out.println("负责人:我允许你请假" + t + "天");
} else {
System.out.println("负责人:你去问问经理");
getSuccessor().handleRequest(t);
}
}
}
class Leader extends Handler {
@Override
public void handleRequest(double t) {
if (t <= 0.5) {
System.out.println("组长:我允许你请假" + t + "天");
} else {
System.out.println("组长:你去问问负责人");
getSuccessor().handleRequest(t);
}
}
}
class Member extends Handler {
@Override
public void handleRequest(double t) {
if (t <= 0) {
System.out.println("员工:我要加班!");
} else {
System.out.println("员工:我要请假"+ t +"天。但我不能擅自离职,我去问问组长");
getSuccessor().handleRequest(t);
}
}
}
客户端:
public class Responsibility {
public static void main(String[] args) {
// 实例化责任对象
Boss boss = new Boss();
Manager manager = new Manager();
Head head = new Head();
Leader leader = new Leader();
Member member = new Member();
// 设置责任链
member.setSuccessor(leader);
leader.setSuccessor(head);
head.setSuccessor(manager);
manager.setSuccessor(boss);
// 员工请假
member.handleRequest(4);
}
}
运行结果:
员工:我要请假4.0天。但我不能擅自离职,我去问问组长
组长:你去问问负责人
负责人:你去问问经理
经理:你去问问老板
老板:我允许你请假4.0天
状态模式
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
角色:
- State(抽象状态类):定义了一个接口,用以封装环境(Context)对象的一个特定状态的行为。
- ConcreteState(具体状态类):实现抽象状态接口,实现了一个状态对应的行为。
- Context(环境类):环境类中维护了一个State对象,它是定义了当前的状态。
备忘录模式
保存一个对象的某个状态,以便在适当的时候恢复对象。
角色:
- 备忘录对象
- 发起人对象
- 负责人对象
发起人内部建立一个内部类——备忘录。
储存时:
调用发起人的方法,创建一个备忘录对象将现在的状态储存起来。
再调用负责人的方法,通过再接口将备忘录对象储存在负责人对象中
然后恢复的时候:
将备忘录对象从负责人对象中取出。
将发起人对象的状态恢复成备忘录对象所存储起来的状态
应用场景:
- 后悔药。(你在想peach呢👺)
- 打游戏时的存档。
- Windows 里的 ctrl + z。
- IE 中的后退。
- 数据库的事务管理。
装饰者模式
装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展,而若我们用继承来完成对类的扩展只能在编译时实现,可以比较动态地对对象进行扩展,某些情况下,装饰者模式比继承更加灵活。
其中有四个角色:
- Component (被共同实现的接口)
- ConcreteComponent (具体的被装饰者)
- Decorator (抽象的装饰者)
- ConcreteDecorator (具体的装饰者)
废话不多说,直接举例子:
public class DecoratorMode {
public static void main(String[] args) {
// 被A装饰的
Component concreteComponentAndA = new ConcreteDecoratorA(new ConcreteComponent());
System.out.println(concreteComponentAndA.description());
// 被B装饰的
Component concreteComponentAndB = new ConcreteDecoratorB(new ConcreteComponent());
System.out.println(concreteComponentAndB.description());
}
}
// Component (被共同实现的接口)
interface Component {
String description();
}
// ConcreteComponent (具体的被装饰者)
class ConcreteComponent implements Component {
@Override
public String description() {
return "ConcreteComponent";
}
}
// Decorator (抽象的装饰者)
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
}
// ConcreteDecoratorA (具体的装饰者A)
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public String description() {
return component.description() + " + ConcreteDecoratorA";
}
}
// ConcreteDecorator (具体的装饰者B)
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public String description() {
return component.description() + " + ConcreteDecoratorB";
}
}
运行结果:
ConcreteComponent + ConcreteDecoratorA
ConcreteComponent + ConcreteDecoratorB