【设计模式】常用的23种设计模式(一)
简介
常用的设计模式分三大类:
创建型模式(Creational Patterns)
结构型模式(Structural Patterns)
行为型模式(Behavioral Patterns)
本章主要来介绍下常用的5种创建型设计模式。
创建型模式(Creational Patterns)
创建型模式提供了一种创建对象同时又隐藏创建逻辑的方式,而不是使用new直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
共5种:
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
1、工厂方法模式(Factory Method Pattern)
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
工厂方法模式分以下三种:
1.1、普通工厂模式
建立一个工厂类,对实现统一接口的一些类进行实例的创建。
举例说明:
首先,创建统一接口:
public interface Sender {
public void sender();
}
其次,创建统一接口的实现类:
public class EmailSender implements Sender {
@Override
public void sender() {
System.out.println("send email ...");
}
}
public class SmsSender implements Sender {
@Override
public void sender() {
System.out.println("send sms ...");
}
}
最后,创建工厂类:
public class SenderFactory {
public Sender produce(String type) {
if ("email".equals(type)) {
return new EmailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
}
return null;
}
}
测试类:
public class SimpleFactoryTest {
public static void main(String[] args) {
SenderFactory factory = new SenderFactory();
// 发送邮件
Sender sender = factory.produce("email");
sender.sender();
// 发送短信
Sender smsSender = factory.produce("sms");
smsSender.sender();
}
}
输出:
send email ...
send sms ...
1.2、多工厂方法模式
多工厂方法模式是对普通工厂模式的改进,如果传入的字符串有误,就不能正确创建对象,而多工厂方法模式是提供多个工厂方法,分别创建不同对象。
所以工厂类修改为:
public class SenderFactory {
public Sender produceEmail() {
return new EmailSender();
}
public Sender produceSms() {
return new SmsSender();
}
}
测试类:
public class ManyFactoryTest {
public static void main(String[] args) {
SenderFactory factory = new SenderFactory();
// 发送邮件
Sender sender = factory.produceEmail();
sender.sender();
// 发送短信
Sender smsSender = factory.produceSms();
smsSender.sender();
}
}
输出:
send email ...
send sms ...
1.3、静态工厂方法模式
将上面多个工厂方法模式里面的工厂方法置为静态的,不需要创建工厂实例,直接调用即可。
则工厂类优化为:
public class SenderFactory {
public static Sender produceEmail() {
return new EmailSender();
}
public static Sender produceSms() {
return new SmsSender();
}
}
测试类:
public class StaticFactoryTest {
public static void main(String[] args) {
// 发送邮件
Sender sender = SenderFactory.produceEmail();
sender.sender();
// 发送短信
Sender smsSender = SenderFactory.produceSms();
smsSender.sender();
}
}
输出:
send email ...
send sms ...
至此,工厂方法模式介绍完毕,下面介绍抽象工厂模式。
2、抽象工厂模式(Abstract Factory Pattern)
工厂方法模式有一个问题,就是类的创建依赖于工厂类;也就是说如果想要拓展程序,必须对工厂类进行修改,这违反了开闭原则。如何解决这个问题,这时就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,则只需要增加新的工厂类就可以,不需要修改之前的代码。
举例说明:
首先,创建统一接口:
public interface Sender {
public void sender();
}
其次,创建统一接口的实现类:
public class EmailSender implements Sender {
@Override
public void sender() {
System.out.println("send email ...");
}
}
public class SmsSender implements Sender {
@Override
public void sender() {
System.out.println("send sms ...");
}
}
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("send sms ...");
}
}
最后,对每个实现类分别创建工厂类:
public class EmailSenderFactory implements Provider {
@Override
public Sender produce() {
return new EmailSender();
}
}
public class SmsSenderFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
public class IMSenderFactory implements Provider {
@Override
public Sender produce() {
return new IMSender();
}
}
测试类:
public class AbstFactoryTest {
public static void main(String[] args) {
// 发送Email
Provider provider = new EmailSenderFactory();
Sender sender = provider.produce();
sender.send();
// 发送Sms
Provider smsProvider = new SmsSenderFactory();
Sender smsSender = smsProvider.produce();
smsSender.send();
// 发送IM
Provider imProvider = new IMSenderFactory();
Sender imSender = imProvider.produce();
imSender.send();
}
}
输出:
send email ...
send sms ...
send IM ...
至此,抽象工厂模式就介绍完毕,下面开始介绍单例模式。
3、单例模式(Singleton Pattern)
在JVM内存中,只实例化一次。
单例类:
public class Singleton {
/** 持有私有静态实例,防止被引用;此处赋值为null,目的是延迟加载 */
private static Singleton instance = null;
/** 私有化构造函数,防止直接实例化 */
private Singleton() {}
/** 获取实例对象 */
public Singleton getInstance() {
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
/** 如果该对象被用于序列化,此方法可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return instance;
}
}
此单例类防止了直接通过构造方法创建实例,同时在一定程度上解决了多线程环境下重复创建实例的问题。但由于Java创建对象和赋值操作是分两步执行的,而且JVM并不保证两个操作的顺序,即有可能出现先赋值,然后再创建实例。所以我们继续优化使用内部类来解决此问题。
单例类:
public class Singleton {
/** 持有私有静态实例,防止被引用;此处赋值为null,目的是延迟加载 */
private static Singleton instance = null;
/** 私有化构造函数,防止直接实例化 */
private Singleton() {}
/** 使用内部类维护单例 */
private static class SingletonFactory {
private static Singleton singleton = new Singleton();
}
/** 获取实例对象 */
public Singleton getInstance() {
return SingletonFactory.singleton;
}
/** 如果该对象被用于序列化,此方法可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return instance;
}
}
至此,单例模式就介绍完毕,下面开始介绍建造者模式。
4、建造者模式(Builder Pattern)
工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象。工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象。
和前面的示例一样,一个Sender接口,两个实现类MailSender和SmsSender。
最后,建造者类如下:
public class Builder {
private List<Sender> senderList = new ArrayList();
public List<Sender> produceEmailSender(int count) {
for (int i = 0; i < count; i++) {
senderList.add(new EmailSender());
}
return senderList;
}
public List<Sender> produceSmsSender(int count) {
for (int i = 0; i < count; i++) {
senderList.add(new SmsSender());
}
return senderList;
}
}
测试类:
public class BuilderTest {
public static void main(String[] args) {
Builder builder = new Builder();
builder.produceEmailSender(5);
}
}
所以与工厂模式的区别就是:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象,多个部分。因此,是选择工厂模式还是建造者模式,依实际情况而定。
5、原型模式(Prototype Pattern)
通过复制现有实例来创建新的实例,即创建对象的克隆。
原型模式的本质就是clone
可以解决构建复杂对象的资源消耗问题,能在某些场景中提升构建对象的效率;还有一个重要用途是保护性拷贝,可以通过返回一个拷贝对象的形式,实现只读的限制;
原型类只需要实现Cloneable接口,覆写clone方法,此处的重点是调用super.clone()方法。
扩展:
深拷贝和浅拷贝
浅拷贝:将一个对象复制后,基本数据类型的变量重新创建,引用类型还指向原对象所指的。
深拷贝:将一个对象复制后,不论是基本数据类型还是引用类型,都是 重新创建的。
(完)