设计模式是一套前人总结下来的,被多数人知晓的,经过分类编目的、代码设计经验的总结。使用设计模式可以使代码重构(MVC->MVP设计模式也是为了代码的解耦用的)、让代码具有大多数人知道的格式,便于理解调试,同时代码可靠性更高。看一看Google的源码,再看看自己的代码,真得特别想吐,并且维护起来也很难。
在我看来,项目只有在一次一次的高质量重构,功能才会越写越多,越写越轻松。
1. 创建型: 单例模式、抽象工厂模式、 建造者模式、 工厂模式、原型模式。
2. 结构型: 适配器模式、桥接模式、 装饰模式、组合模式、外观模式、享元模式、代理模式、 装饰模式 (静态代理)。
3. 行为型: 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
------------------------------创建型--------------------------
单例
第一种 懒汉
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
第二种 饿汉
public class HttpEngineAuto {
private static HttpEngineAuto ourInstance = new HttpEngineAuto();
public static HttpEngineAuto getInstance() {
return ourInstance;
}
private HttpEngineAuto() {
}
}
工厂模式:
最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。
但是在一些情况下, new操作符直接生成对象会带来一些问题。
举例来说, 许多类型对象的创造需要一系列的步骤:
1.你可能需要计算或取得对象的初始设置;
2.选择生成哪个子对象实例;
3.或在生成你需要的对象之前必须先生成一些辅助功能的对象。
在这些情况,新对象的建立就需要一个 “过程”,不仅是一个操作。
也许在下面情况下你可以考虑使用工厂方法模式:
1)当客户程序不需要知道要使用对象的创建过程。
2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
1、普通工厂模式
public interface Sender {
public void Send();
}
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("mail");
}
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("sms");
}
}
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}
2、普通工厂模式升级 参考: GsonConverterFactory
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类
public interface Sender {
void Send();
abstract class Factory {
Sender createMailSender() {
return null;
}
Sender createSmsSender() {
return null;
}
}
}
public class SendMessageFactory extends Sender.Factory {
public static SendMessageFactory create() {
return new SendMessageFactory();
}
@Override
Sender createMailSender() {
return new MailSender();
}
@Override
Sender createSmsSender() {
return new SmsSender();
}
}
public static void main(String[] args) {
SendMessageFactory msgFactory = SendMessageFactory.create();
Sender sender = msgFactory.createMailSender();
sender.Send();
}
3、静态工厂方法模式
public class SendFactory {
public static Sender produceMail() {
return new MailSender();
}
public static Sender produceSms() {
return new SmsSender();
}
}
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.send();
}
}
4、抽象工厂模式
工厂方法模式有一个问题:类的创建依赖工厂类,也就是说,如果想要工厂创建更多的类
必须对工厂类进行修改,这样违背了必要原则,所以从设计角度考虑,有一定的问题。
如何解决呢? 用抽象工厂模式,创建多个工厂类,这样一旦需要创建新的功能,直接增加
新的工厂类就可以了,不需要修改之前的代码。
public interface Creator {
public Sender produce();
}
public class SendMailFactory implements Creator {
@Override
public Sender produce() {
return new MailSender();
}
}
public class SendSmsFactory implements Creator {
@Override
public Sender produce() {
return new SmsSender();
}
}
public static void main(String[] args) {
Creator creator = new SendMailFactory();
Sender sender = creator.produce();
sender.Send();
}
建造者模式:
工厂模式是提供创建一系列有类似功能的模式;而建造者模式则是为创建一个类之前选择不同配置属性的模式。
建造者模式固定写法:
public class Phone {
private String number;
private String manufacturer;
private static final String NUMBER = "18790861281";
private static final String MANUFACTURER = "vivox6";
Phone(Phone.Builder builder) {
this.number = builder.number;
this.manufacturer = builder.manufacturer;
}
public void call(String toNumber) {
System.out.println(number + " call to " + toNumber);
}
public static final class Builder {
String number;
String manufacturer;
public Builder() {
this.number = NUMBER;
this.manufacturer = MANUFACTURER;
}
public Builder setNumber(String number) {
this.number = number;
return this;
}
public Builder setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
return this;
}
public Phone builde() {
return new Phone(this);
}
}
}
public static void main(String[] args) {
Phone samsung = new Phone.Builder()
.setManufacturer("samsung")
.setNumber("13121317298")
.builde();
samsung.call("110");
}
---------------------------结构型---------------------------
适配器模式适配器模式将某个类的接口转换成客户端期望的另一个接口表示,
目的是消除由于接口不匹配所造成的类的兼容性问题。
主要分为三类
类的适配器模式、对象的适配器模式、接口的适配器模式。
一、类的适配器模式
public class Source {
public void method1() {
System.out.println("this is original method!");
}
}
public interface Targetable {
/* 与原类中的方法相同 */
public void method1();
/* 新类的方法 */
public void method2();
}
public class Adapter extends Source implements Targetable {
@Override
public void method2() {
System.out.println("this is the targetable method!");
}
}
public class AdapterTest {
public static void main(String[] args) {
Targetable target = new Adapter();
target.method1();
target.method2();
}
}
二、对象的适配器模式
基本思路和类的适配器模式相同,只是将 Adapter 类作修改,
这次不继承 Source 类,而是持有 Source 类的实例,
以达到解决兼容性的问题。
public class Wrapper implements Targetable {
private Source source;
public Wrapper(Source source) {
super();
this.source = source;
}
@Override
public void method2() {
System.out.println("this is the targetable method!");
}
@Override
public void method1() {
source.method1();
}
}
public class AdapterTest {
public static void main(String[] args) {
Source source = new Source();
Targetable target = new Wrapper(source);
target.method1();
target.method2();
}
}
三、接口的适配器模式
接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,
当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,
因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这
个问题,我们引入了接口的适配器模式,借助于一个抽象类,
该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,
只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。
装饰模式
装饰模式就是给一个对象增加一些新的功能,而且是动态的,
要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
public interface Sourceable {
public void method();
}
public class Source implements Sourceable {
@Override
public void method() {
System.out.println("the original method!");
}
}
public class Decorator implements Sourceable {
private Sourceable source;
public Decorator(Sourceable source) {
super();
this.source = source;
}
@Override
public void method() {
System.out.println("before decorator!");
source.method();
System.out.println("after decorator!");
}
}
public class DecoratorTest {
public static void main(String[] args) {
Sourceable source = new Source();
Sourceable obj = new Decorator(source);
obj.method();
}
}
例如:
Collections.synchronizedCollection(c)
Collections.synchronizedCollectionList(list)
Collections.synchronizedCollectionMap(m)
Collections.synchronizedCollectionSet(s)
将原本 线程不安全的 集合装饰为 线程安全的集合
--------------------------行为型---------------------------
观察者
观察者模式很好理解,类似于邮件订阅和 RSS 订阅,当我们浏览一些博客或 wiki 时,
经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。
其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,
并且随着变化!对象之间是一种一对多的关系。
又称 发布-订阅 模式
ListView 中 Observer 的设计模式 ListView中观察者模式源码分析
ListView 充当订阅者
BaseAdapter 充当发布者
ListView.setAdapter(ListAdapter)
1. ListView 的父类会抽取一个主管会重绘界面的类 并实现接口 用于被发布者通知调用
2. new 出这个绘制ListView 界面的类,
3. 注册到 BaseAdapter中,BaseAdapter只以接口的方式接收这个对象
4. 当BaseAdapter调用 notifyDataSetChanged 方法时就会调用 这个接口中的方法用于
刷新ListView
public interface Observer {
public void update();
}
public class Observer1 implements Observer {
@Override
public void update() {
System.out.println("observer1 has received!");
}
}
public class Observer2 implements Observer {
@Override
public void update() {
System.out.println("observer2 has received!");
}
}
public interface Subject {
/*增加观察者*/
public void add(Observer observer);
/*删除观察者*/
public void del(Observer observer);
/*通知所有的观察者*/
public void notifyObservers();
/*自身的操作*/
public void operation();
}
public abstract class AbstractSubject implements Subject {
private Vector<Observer> vector = new Vector<Observer>();
@Override
public void add(Observer observer) {
vector.add(observer);
}
@Override
public void del(Observer observer) {
vector.remove(observer);
}
@Override
public void notifyObservers() {
Enumeration<Observer> enumo = vector.elements();
while (enumo.hasMoreElements()) {
enumo.nextElement().update();
}
}
}
public class MySubject extends AbstractSubject {
@Override
public void operation() {
System.out.println("update self!");
notifyObservers();
}
}
public class ObserverTest {
public static void main(String[] args) {
Subject sub = new MySubject();
sub.add(new Observer1());
sub.add(new Observer2());
sub.operation();
}
}