简介
设计模式(Design Pattern)
设计模式是什么?它是一套理论,由前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。“道可道,非常道”非常适合描述设计模式。
不得不说的六大设计原则
- 单一职责原则:要求我们实现类要职责单一
- 里氏替换原则:要求我们不要破坏继承关系体系
- 依赖倒置原则:要求我们要面向接口编程
- 接口隔离原则:要求我们在设计接口的时候要精简单一
- 迪米特法则:要求我们要降低耦合
- 开闭原则:要求我们对扩展开放,对修改关闭
开始学设计模式
设计模式
-
创建型
- 单例模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
-
结构型
- 适配器模式
- 组合模式
- 装饰模式
- 代理模式
- 享元模式
- 外观模式
- 桥接模式
-
行为型
- 观察者模式
- 策略模式
- 状态模式
- 模板方法模式
- 命令模式
- 解释器模式
- 迭代模式
- 责任链模式
- 访问者模式
- 中介者模式
- 备忘录模式
【单例模式】
单例模式可以说是最容易理解的模式了,也是用的最多的模式之一。
什么是单例模式?确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。什么时候需要使用单例模式呢?如果某个类,创建时需要消耗很多资源,即new出这个类的代价很大;或者是这个类占用很多内存,如果创建太多这个类实例会导致内存占用太多。
懒汉式
public class Singleton{
// 重点 volatitle 关键字的使用
private volatile static Singleton instance;
private Singleton(){};
public static Singleton getInstance(){
if (instance == null){
sychronized(Singleton.class){
if (instance == null)
instance=new Singleton();
}
}
return instatnce;
}
}
基于懒汉式+synchronized的通用单例
public class Singleton<T> {
private static final ConcurrentMap<Class, Object> INSTANCE_MAP = new ConcurrentHashMap<Class, Object>();
private Singleton(){}
public static <T> T getInstance(Class<T> type){
Object o = INSTANCE_MAP.get(type);
if (o == null){
synchronized (INSTANCE_MAP){
try {
o = type.newInstance();
INSTANCE_MAP.put(type, o);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return (T) o;
}
}
在Android中的应用
//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);
【建造者模式】
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
什么情况下使用该模式呢?
主要是在创建某个对象时,需要设定很多的参数(通过setter方法),但是这些参数必须按照某个顺序设定,或者是设置步骤不同会得到不同结果。
public class Student {
private final long id; // 必须参数
private final String name; // 非必须
private final int age;
private Student(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public long getId() {
return id;
}
public static class Builder{
private final long id; // 必须参数
private String name; // 非必须
private int age;
// 返回自身的引用this,这主要是用于链式调用
public Builder(long id) {
this.id = id;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Student build(){
Student student = new Student(this);
// Builder另一个特性可以对参数进行合法性验证
if (student.getAge() > 120){
// Builder模式是非线程安全的,如果要在Builder内部类中检查一个参数的合法性,必需要在对象创建完成之后再检查
throw new IllegalStateException("年龄超出限制");
}
return student;
}
}
}
注意:
- Student的构造方法是私有的,也就是说我们不能直接new出来
- Student的属性用final修饰,并且我们在构造方法中都为他们进行了初始化操作,只提供了getter方法
- 使用builder模式构造出来的对象有更好的可读性
- Builder的属性中只给我们必须的属性添加的final修饰,所以必须在构造方法中为他们初始化
// 优美的链式调用
Student student = new Student.Builder(1)
.setName("张三")
.setAge(18)
.build();
在Android中的应用
- Android中的AlertDialog.Builder
private void showDialog(){
AlertDialog.Builder builder=new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon);
builder.setTitle("Title");
builder.setMessage("Message");
builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//TODO
}
});
builder.setNegativeButton("Button2", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//TODO
}
});
builder.create().show();
}
- OkHttp中OkHttpClient的创建
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(getCache())
.addInterceptor(new HttpCacheInterceptor())
.addInterceptor(new LogInterceptor())
.addNetworkInterceptor(new HttpRequestInterceptor())
.build();
【工厂模式】
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方式模式使一个类的实例化延迟到其子类。
public abstract class Product{
// 产品类的公共方法
public void method1(){
// 业务逻辑
}
public abstract void method2();
}
public class ConcreteProductA extends Product {
@Override
public void method2() {
// 产品A的业务逻辑
}
}
public class ConcreteProductB extends Product {
@Override
public void method2() {
// 产品B的业务逻辑
}
}
public abstract class Creator {
// 创建一个产品对象
public abstract <T extends Product > T createProduct(Class<T> clazz);
}
public class ConcreteCreator extends Creator {
@Override
public <T extends Product> T createProduct(Class<T> clazz) {
Product product = null;
try {
product = (Product) Class.forName(clazz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) product;
}
}
在Android中的应用
//抽象产品:Runnable
public interface Runnable {
public abstract void run();
}
//具体产品:Thread
public class Thread implements Runnable {
//构造方法
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
@Override
//实现抽象产品的抽象方法
public void run() {
if (target != null) {
target.run();
}
}
//其他代码略
}
//抽象工厂:ThreadFactory
public interface ThreadFactory {
Thread newThread(Runnable r);
}
//具体工厂:AsyncTask中的实现
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
//实现抽象工厂的抽象方法
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());//返回Thread这个产品
}
};
【抽象工厂模式】
为创建一组相关或者是相互依赖的对象提供一个接口,而不需要制定他们的具体类。
//抽象产品类-- CPU
public abstract class CPU {
public abstract void showCPU();
}
//抽象产品类-- 内存
public abstract class Memory {
public abstract void showMemory();
}
//抽象产品类-- 硬盘
public abstract class HD {
public abstract void showHD();
}
创建具体产品类
//具体产品类-- Intet CPU
public class IntelCPU extends CPU {
@Override
public void showCPU() {
System.out.println("Intet CPU");
}
}
//具体产品类-- AMD CPU
public class AmdCPU extends CPU {
@Override
public void showCPU() {
System.out.println("AMD CPU");
}
}
//具体产品类-- 三星 内存
public class SamsungMemory extends Memory {
@Override
public void showMemory() {
System.out.println("三星 内存");
}
}
//具体产品类-- 金士顿 内存
public class KingstonMemory extends Memory {
@Override
public void showMemory() {
System.out.println("金士顿 内存");
}
}
//具体产品类-- 希捷 硬盘
public class SeagateHD extends HD {
@Override
public void showHD() {
System.out.println("希捷 硬盘");
}
}
//具体产品类-- 西部数据 硬盘
public class WdHD extends HD {
@Override
public void showHD() {
System.out.println("西部数据 硬盘");
}
}
创建抽象工厂类
//抽象工厂类,电脑工厂类
public abstract class ComputerFactory {
public abstract CPU createCPU();
public abstract Memory createMemory();
public abstract HD createHD();
}
创建具体工厂类
//具体工厂类--联想电脑
public class LenovoComputerFactory extends ComputerFactory {
@Override
public CPU createCPU() {
return new IntelCPU();
}
@Override
public Memory createMemory() {
return new SamsungMemory();
}
@Override
public HD createHD() {
return new SeagateHD();
}
}
//具体工厂类--华硕电脑
public class AsusComputerFactory extends ComputerFactory {
@Override
public CPU createCPU() {
return new AmdCPU();
}
@Override
public Memory createMemory() {
return new KingstonMemory();
}
@Override
public HD createHD() {
return new WdHD();
}
}
//具体工厂类--惠普电脑
public class HpComputerFactory extends ComputerFactory {
@Override
public CPU createCPU() {
return new IntelCPU();
}
@Override
public Memory createMemory() {
return new KingstonMemory();
}
@Override
public HD createHD() {
return new WdHD();
}
}
优点:
- 封装性,每个产品的实现类不是高层模块要关心的,它要关心的是接口是抽象。
- 产品族内的约束为非公开状态。例如联想电脑使用的是IntelCpu+三星内存+希捷的盘,具体的产品族内的约束是在工厂内实现的。
缺点:
抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?比如我们增加一个主板,抽象类需要增加createBoard(),然后实现类都需要去修改,这就严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约,改变契约有与契约有关系的代码都要修改,这就是有毒代码。上面说的是产品族内扩展困难,但是品牌类型扩建容易,只要增加一个工厂类复制新增加出来的产品生产任务即可。
工厂方法模式与抽象工厂模式比较
- 在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法具有唯一性。
- 抽象工厂模式则可以提供多个产品对象,而不是单一的产品对象
【观察者模式】
待续。。。
【代理模式】
待续。。。
【策略模式】
待续。。。
【原型模式】
待续。。。
【状态模式】
待续。。。
【命令模式】
待续。。。
【装饰模式】
待续。。。
【适配器模式】
待续。。。