原则
设计模式的六大原则:
- 单一职责
- 开闭 对扩展开发;对修改关闭
- 依赖倒置 高模块不依赖低模块 高模块和低模块都依赖抽象;抽象不依赖具体实现 具体实现依赖抽象
- 里氏替换 子类可以替换父类;父类不一定可以替换子类
- 迪马特法则 一个类尽可能少的知道其他类;解耦
- 接口隔离 不依赖不需要的接口 类之间的依赖关系应该建立在最小的接口(接口尽量细化 不要有太多的方法)上;核心:依赖抽象 不依赖具体
类型
常见的设计模式分为三类:
- 创建型 单例;工厂;建造者
- 行为型 迭代器;观察者;策略
- 结构型 代理;适配器;组合;装饰
分析
- Builder
作用:用户不知道内部构造细节的情况下 控制构造流程
优点:良好的封装性 客户端不必知道产品内部组成细节
场景:相同的方法 不同的执行顺序产生不同的结果 初始化的对象很复杂 参数很多
应用:AlertDialog
栗子:
public class Person {
private String name;
private int sex;
public Person(Builder builder){
this.name=builder.name;
this.sex=builder.sex;
}
public String getName(){
return name;
}
public int getSex(){
return sex;
}
static class Builder {
//Builder需要持有和Person相同的对象
public String name;
public int sex;
public Builder() {
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setSex(int sex) {
this.sex = sex;
return this;
}
// 之所以在build中才构建具体Person对象 应该是处于拓展考虑 比如再来一个student类Builder可以复用
public Person build() {
return new Person(this);
}
}
}
public static void main(String[] args) {
// 达到链式调用的效果
Person person = new Person.Builder().setName("34sir").setSex(1).build();
System.out.println("person::name=" + person.getName() + "---person::sex=" + person.getSex());
}
-
工厂方法
作用:定义用于创建对象的接口 让子类决定实例化哪个类
优点:多态性 灵活;封装性 结构清晰;拓展性;解耦
场景:任何需要生成复杂对象的地方 new 就可以创建的对象无需使用工厂方法
应用:Activity的onCreate
栗子:
//汽车抽象产品
public abstract class CarProduct {
public abstract void born();
}
//汽车抽象工厂
public abstract class CarFactory {
public abstract T createProduct(Class clz);
}
//奥迪Q3
public class AodiQ3 extends CarProduct {
@Override
public void born() {
System.out.println(this.getClass().getSimpleName()+"诞生了!");
}
}
//奥迪Q5
public class AodiQ5 extends CarProduct {
@Override
public void born() {
System.out.println(this.getClass().getSimpleName()+"诞生了!");
}
}
//具体汽车工厂
public class ConcreateCarFactory extends CarFactory {
@Override
public T createProduct(Class clz) {
CarProduct product = null;
try {
// 利用反射+泛型灵活 不需要多个工厂实现类
product= (CarProduct) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T)product;
}
}
public static void main(String [] args){
CarFactory factory=new ConcreateCarFactory();
//生产不同的汽车产品
factory.createProduct(AodiQ3.class).born();
factory.createProduct(AodiQ5.class).born();
}
策略
作用:将算法或策略抽象出来 提供一个同一的接口 不同的算法或策略有不同的实现类 通过注入不同的实现对象来实现算法或策略的动态替换
优点:结构化;解耦 易扩展;封装性
场景:同一问题多种处理方式 行为的差别;同一个抽象类 多个子类 需要使用if-else来选择具体子类
应用:属性动画的插值器-
迭代器
作用:提供一种统一的方法顺序访问一个容器对象中的各个元素 不暴露对象中的内部细节
优点:
场景:遍历容器对象
应用:查询数据库时使用的Cursor
栗子:
//迭代器接口 主要的两个方法:hasNext next();
public interface Iterator {
boolean hasNext();
//泛型更具灵活性
T next();
}
//容器接口
public interface Aggregate {
void add(T obj);
void remove(T obj);
Iterator interator();// 获取容器的迭代器
}
// 具体迭代器
public class ConcreteIterator implements Iterator{
private List list=new ArrayList<>();
private int cursor=0;
public ConcreteIterator(List list) {
this.list = list;
}
@Override
public boolean hasNext() {
return cursor!=list.size();
}
@Override
public T next() {
T obj = null;
if(this.hasNext()){
obj=list.get(cursor++);
}
return obj;
}
}
//具体容器类
public class ConcreteAggregate implements Aggregate {
private List list = new ArrayList<>();
@Override
public void add(T obj) {
list.add(obj);
}
@Override
public void remove(T obj) {
list.remove(obj);
}
@Override
public Iterator interator() {
return new ConcreteIterator<>(list);
}
}
public static void main(String[] args) {
//此例实际实现了对容器对迭代 实际上Iterator已经存在
Aggregate aggregate = new ConcreteAggregate<>();
aggregate.add("ckc");
aggregate.add("34sir");
Iterator iterator = aggregate.interator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
-
代理
作用:为某个对象提供代理 以控制对这个对象的访问
优点:没什么缺点 强调控制 隔离
场景:无法或者不想直接访问某个对象
应用:ActivityManagerProxy代理ActivityManagerService
栗子:包含静态代理和动态代理
//抽象主题
public interface Subject {
void visit();
}
//真实主题
public class RealSubject implements Subject{
@Override
public void visit() {
System.out.println("具体主题 具体逻辑");
}
}
//静态代理类
public class ProxySubject implements Subject{
RealSubject subject;
public ProxySubject(RealSubject subject) {
this.subject = subject;
}
@Override
public void visit() {
//调用受代理真实逻辑
subject.visit();
}
}
//动态代理类
public class DynamicProxySubject implements InvocationHandler{
Subject subject;
public DynamicProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
return method.invoke(subject,objects);
}
}
public static void main(String[] args) {
//静态代理
ProxySubject proxy=new ProxySubject(new RealSubject());
proxy.visit();
//动态代理
Subject subject=new RealSubject();
DynamicProxySubject dynamicProxySubject=new DynamicProxySubject(subject);
ClassLoader loader=subject.getClass().getClassLoader();
//Proxy.newProxyInstance 此方法是实现动态代理的关键
Subject subjecter= (Subject) Proxy.newProxyInstance(loader,new Class[]{Subject.class},dynamicProxySubject);
subjecter.visit();
}
-
观察者
作用:定义对象间一对多的依赖关系 使得当一个对象改变 所有依赖于他的对象都会得到通知并更新
优点:将观察者和被观察者解耦
场景:消息交换 订阅-发布系统 消息队列 事件总线等
应用:Adapter#notifyDataSetChanged;BroadcastReceiver
栗子:
//抽象主题 订阅者
public interface Subject {
void notifyData();
void addObserver(Observer observer);
void deleteObserver(Observer observer);
}
//抽象观察者
public interface Observer {
void update(String msg);
}
//具体订阅者
public class ConcreteSubject implements Subject {
// 之所有使用Vector 是因为其线程安全
private Vector observers = new Vector<>();
@Override
public void notifyData() {
Enumeration enumo = observers.elements();
while (enumo.hasMoreElements()) {
enumo.nextElement().update("hello world");
}
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
}
//具体观察者
public class ConcreteObserver implements Observer{
String msg;
@Override
public void update(String msg) {
this.msg = msg;
System.out.println("ConcreteSubject的msg更新成" + this.msg);
}
}
public static void main(String [] args){
Subject subject=new ConcreteSubject();
subject.addObserver(new ConcreteObserver());
subject.notifyData();
}
-
组合
作用:将对象组合成树形结构 以表示“部分-整体”的层次结构 使得用户对单个对象和组合对象的访问具有一致性
优点:清楚的定义分层次的复杂对象 简化高层模块的代码 递归组合形成复杂的树形结构
场景:一个整体中能够独立出部分模块和功能
应用:View和ViewGroup的嵌套组合
栗子:
1.安全组合
//抽象根节点
public abstract class Component {
protected String name; //节点
public Component(String name) {
this.name = name;
}
//具体由子类实现
public abstract void doSomething();
}
//枝干
public class Composite extends Component {
public Composite(String name) {
super(name); // 调用父类的方法
}
private List composites = new ArrayList<>();
@Override
public void doSomething() {
System.out.println(name); //此句为具体实现的逻辑
if (null != composites) {
for (Component c : composites) {
c.doSomething();
}
}
}
public void addChild(Component c) {
composites.add(c);
}
public void remove(Component c) {
composites.remove(c);
}
public Component getChild(int index) {
return composites.get(index);
}
}
//叶子
public class Leaf extends Component {
public Leaf(String name) {
super(name); // 调用父类的方法
}
@Override
public void doSomething() {
System.out.println(name);
}
}
//叶子
public static void main(String[] args) {
// 与透明组合模式的区别
Composite root = new Composite("root");
Composite branchOne = new Composite("branchone");
Composite branchTwo = new Composite("branchtwo");
Leaf leafOne = new Leaf("leafone");
Leaf leafTwo = new Leaf("leaftwo");
branchOne.addChild(leafOne);
branchTwo.addChild(leafTwo);
root.addChild(branchOne);
root.addChild(branchTwo);
root.doSomething();
}
2.透明组合
//抽象根节点
public abstract class Component {
protected String name; //节点
public Component(String name) {
this.name = name;
}
//具体由子类实现
public abstract void doSomething();
public abstract void addChild(Component c);
public abstract void removeChild(Component c);
public abstract Component getChild(int index);
}
//枝干
public class Composite extends Component {
public Composite(String name) {
super(name); // 调用父类的方法
}
private List composites = new ArrayList<>();
@Override
public void doSomething() {
System.out.println(name); //此句为具体实现的逻辑
if (null != composites) {
for (Component c : composites) {
c.doSomething();
}
}
}
public void addChild(Component c) {
composites.add(c);
}
@Override
public void removeChild(Component c) {
composites.remove(c);
}
public Component getChild(int index) {
return composites.get(index);
}
}
//叶子
public class Leaf extends Component {
public Leaf(String name) {
super(name); // 调用父类的方法
}
@Override
public void doSomething() {
System.out.println(name);
}
@Override
public void addChild(Component c) {
throw new UnsupportedOperationException("叶子无法添加子节点");
}
@Override
public void removeChild(Component c) {
throw new UnsupportedOperationException("叶子没有子节点");
}
@Override
public Component getChild(int index) {
throw new UnsupportedOperationException("叶子没有子节点");
}
}
public static void main(String[] args) {
// 与安全组合模式的区别
Component root=new Composite("root");
Component branchOne=new Composite("branchone");
Component branchTwo = new Composite("branchtwo");
Component leafOne=new Leaf("leafone");
Component leafTwo=new Leaf("leaftwo");
branchOne.addChild(leafOne);
branchTwo.addChild(leafTwo);
root.addChild(branchOne);
root.addChild(branchTwo);
root.doSomething();
}
-
适配器
作用:把一个类的接口变换成客户端所期待的另一个接口 将两个不兼容的类融合在一起
优点:更好的复用性;更好的拓展性 适配的同时可以开发新功能
场景:兼容老接口
应用:ListView#Adapter
栗子:
//迭代器接口 主要的两个方法:hasNext next();
public interface Iterator {
boolean hasNext();
//泛型更具灵活性
T next();
}
//容器接口
public interface Aggregate {
void add(T obj);
void remove(T obj);
Iterator interator();// 获取容器的迭代器
}
// 具体迭代器
public class ConcreteIterator implements Iterator{
private List list=new ArrayList<>();
private int cursor=0;
public ConcreteIterator(List list) {
this.list = list;
}
@Override
public boolean hasNext() {
return cursor!=list.size();
}
@Override
public T next() {
T obj = null;
if(this.hasNext()){
obj=list.get(cursor++);
}
return obj;
}
}
//具体容器类
public class ConcreteAggregate implements Aggregate {
private List list = new ArrayList<>();
@Override
public void add(T obj) {
list.add(obj);
}
@Override
public void remove(T obj) {
list.remove(obj);
}
@Override
public Iterator interator() {
return new ConcreteIterator<>(list);
}
}
public static void main(String[] args) {
//此例实际实现了对容器对迭代 实际上Iterator已经存在
Aggregate aggregate = new ConcreteAggregate<>();
aggregate.add("ckc");
aggregate.add("34sir");
Iterator iterator = aggregate.interator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
-
装饰
作用:动态的给一个对象添加一些额外的指责 继承关系的一种替代方案
优点:动态增加类的功能
场景:需要透明并且动态的扩展类的功能
应用:ContextWrapper装饰ContextImpl
栗子:
// 抽象组件
public abstract class Component {
public abstract void operate();
}
//抽象装饰者
public abstract class Decorator extends Component {
private Component component;//持有一个组件
public Decorator(Component component) {
this.component = component;
}
@Override
public void operate() {
component.operate();
}
}
// 具体组件
public class ConcreteComponent extends Component{
@Override
public void operate() {
}
}
//具体装饰类
public class ConcreteDecortor extends Decorator {
public ConcreteDecortor(Component component) {
super(component);
}
@Override
public void operate() {
operateA(); //operateA和operateB增强组件的功能
super.operate();
operateB();
}
public void operateA() {
}
public void operateB() {
}
}
public static void main(String[] arg) {
Component component = new ConcreteComponent();
//ConcreteDecortor装饰Component
Decorator decorator = new ConcreteDecortor(component);
decorator.operate();
}
-
享元
作用:缓存可共享的对象 避免创建过多的对象 减少内存使用量
场景:大量重复对象
应用:Message#obtain
栗子:
//抽象车票接口
public interface Ticket {
public void showTicketInfo(String bunk);
}
//车票工厂
public class TicketFactory {
// 首先选择一种容器缓存
static Map ticketMap = new ConcurrentHashMap<>();
public static Ticket getTicket(String from, String to) {
String key = from + "" + to;
if (ticketMap.containsKey(key)) {
return ticketMap.get(key);
} else {
Ticket ticket = new TrainTicket(from, to);
ticketMap.put(key, ticket);
return ticket;
}
}
}
//火车票
public class TrainTicket implements Ticket {
public String from; //始发地
public String to; //目的地
public int price;
public TrainTicket(String from, String to) {
this.from = from;
this.to = to;
}
@Override
public void showTicketInfo(String bunk) {
price = new Random().nextInt(300);
System.out.println("购买从" + from + "到" + to + "的" + bunk + "火车票" + ",价格:" + price);
}
}
public static void main(String [] args){
Ticket ticketOne= TicketFactory.getTicket("苏州","上海");
ticketOne.showTicketInfo("上铺");
Ticket ticketTwo= TicketFactory.getTicket("苏州","上海");
ticketTwo.showTicketInfo("下铺");
Ticket ticketThree= TicketFactory.getTicket("苏州","上海");
ticketThree.showTicketInfo("站票");
}