今个是十一假期第二天,奖励自己学习一下设计模式,很久之前就想学习一下了,但是真的是时间有限,哈哈,终于有时间了,话不多说,冲冲冲!
为什么要有设计模式
设计模式(Design Pattern)最重要的目的是为了可重用代码,他带来的好处当然也不止于此,除此之外也可以让代码更容易被理解、更具可靠性。做为一名软件工程师,设计模式的学习是必不可少的。
设计模式的分类
总体来说设计模式可以分成三大类:
创建型模式,有5种:工厂方法模式、抽象方法模式、单例模式、建造者模式、原型模式
结构型模式、有7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为型模式,有11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
设计模式六大原则
1、开闭原则(Open Close Principle)
对扩展开放、对修改关闭
2、里氏代换原则(Liskov Subsititution Principle)
也是OOP的设计原则之一。原则是基类出现的地方,子类也一定可以出现,LSP是继承复用的基础。
3、依赖倒置原则(Dependence Inversion Principle)
面向接口编程,依赖抽象而不依赖具体
4、接口隔离原则(Interface Segregation Principal)
使用多个隔离接口,比使用单个接口要好。目的是降低耦合度。
5、迪米特原则(Demeter Principal)
一个实体尽量少的与其他实体出现交互作用
6、合成复用原则(Composite Reuse Principal)
尽量使用合成方式而不是使用继承
23种设计模式
1、工厂模式
工厂模式的目的是生产对象
package designPattern;
interface Sender {
void send();
}
class MailSender implements Sender{
@Override
public void send() {
System.out.println("mail sender");
}
}
class SmsSender implements Sender{
@Override
public void send() {
System.out.println("sms sender");
}
}
public class Factory {
public Sender produce(String type){
if ("mail".equals(type)) {
return new MailSender();
}else if ("sms".equals(type)) {
return new SmsSender();
}else {
return null;
}
}
}
//多个工厂方法模式
class SendFactory {
public Sender produceMail (){
return new MailSender();
}
public Sender produceSms() {
return new SmsSender();
}
}
//静态工厂
class StaticFactory {
public static Sender produceMail() {
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
2、抽象工厂模式
前面的工厂模式,如果需要拓展程序,需要修改工厂类
interface Sender {
void send();
}
class MailSender implements Sender{
@Override
public void send() {
System.out.println("mail sender");
}
}
class SmsSender implements Sender{
@Override
public void send() {
System.out.println("sms sender");
}
}
interface AbstractFactory{
Sender produce();
}
class MailFactory implements AbstractFactory{
@Override
public Sender produce() {
return new MailSender();
}
}
class SmsFactory implements AbstractFactory{
@Override
public Sender produce() {
return new SmsSender();
}
}
3、单例模式
这种模式的好处是:
1、大型的对象只创建一次,减少开销;
2、减小GC的压力;
3、控制一个类只存在一个对象;
public class Singleton {
//饿汉
private static final Singleton SINGLETON = new Singleton();
public static Singleton getInstance() {
return SINGLETON;
}
}
无法做到懒加载,容易造成内存浪费。
public class Singleton {
//懒汉
private static Singleton singleton = null;
public static Singleton getInstance() {
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
这种懒汉式单例似乎可以解决问题,但是显然是线程不安全的。
public class Singleton {
//懒汉
private static volatile Singleton singleton = null;
public static Singleton getInstance() {
if (singleton == null){
synchronized (Singleton.class) {
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
这种双锁校验方式实现的单例线程是安全的,同时保证了高效率。
还有一种常用的单例模式的写法,是通过内部类实现的,代码如下
public class Singleton {
//内部类
private static class SingletonFactory {
private static Singleton singleton = new Singleton();
}
public Singleton getInstance() {
return SingletonFactory.singleton;
}
}
4、建造者模式
模式的结构
建造者(Builder)模式的主要角色如下。
产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
package designPattern;
class Product {
private String partA;
private String partB;
private String partC;
public String getPartA() {
return partA;
}
public void setPartA(String partA) {
this.partA = partA;
}
public String getPartB() {
return partB;
}
public void setPartB(String partB) {
this.partB = partB;
}
public String getPartC() {
return partC;
}
public void setPartC(String partC) {
this.partC = partC;
}
public String show() {
return this.toString();
}
}
public abstract class Builder {
//创建产品对象
public Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回产品对象
public Product getResult() {
return product;
}
}
class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
this.product.setPartA("A");
}
@Override
public void buildPartB() {
this.product.setPartB("B");
}
@Override
public void buildPartC() {
this.product.setPartC("C");
}
}
class Director {
private Builder builder;
//根据需要传入不同的Builder
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}