一、简介
1.背景
2.什么是设计模式
3.为什么使用设计模式
二、单例模式(Singleton)
1.概述
单例模式指的是一个类只能有一个实例,这样的类被称为单例类,或者单态类,即Singleton Class。
2.单例类的特点
1)单例类只可有一个实例
2)它必须自己创立这唯一的一个实例
3)它必须给所有其他的类提供自己这一实例
3.单例模式的实现
单例模式有两种常见的实现方式,被称为饿汉式和懒汉式。
饿汉式:加载类的时候就初始化一个实例。
懒汉式:加载类的时候不初始化,当第一次使用实例时才初始化。
4.单例类的特点总结
1)构造方法是private权限,保证其他类无法创建该类实例,只能该类自身创建
2)声明一个static修饰的自身实例,保证该实例永远只是一个
3)提供一个public方法,返回定义的static自身实例
5.代码演示
5.1饿汉式
public class EagerSingleton {
//饿汉式单例:声明并创建一个自身的static实例
private static EagerSingleton instance = new EagerSingleton();
//构造方法是private
private EagerSingleton() {
}
//提供静态public方法,返回自己创建的唯一实例
public static EagerSingleton getInstance() {
return instance;
}
}
5.2懒汉式
public class LazySingleton {
//懒汉式单例:只声明,不创建
private static LazySingleton instance = null;
//构造方法为private
private LazySingleton() {
}
//当第一次调用getInstance方法时,创建唯一实例
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
6.API中的单例模式
API中的Runtime类是一个单例类
没有公共的构造方法
提供静态方法getRuntime()返回该类实例
public static void main(String[] args) {
//获得多个实例,输出后如果地址相同,说明是同一个实例
EagerSingleton eager1 = EagerSingleton.getInstance();
EagerSingleton eager2 = EagerSingleton.getInstance();
System.out.println(eager1);
System.out.println(eager2);
System.out.println("--------------------");
LazySingleton lazy1 = LazySingleton.getInstance();
LazySingleton lazy2 = LazySingleton.getInstance();
System.out.println(lazy1);
System.out.println(lazy2);
System.out.println("--------------------");
Runtime r1 = Runtime.getRuntime();
Runtime r2 = Runtime.getRuntime();
Runtime r3 = Runtime.getRuntime();
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
try {
r1.exec("calc.exe");//打开计算机
} catch (IOException e) {
e.printStackTrace();
}
}
三、适配器模式(Adapter)
1.概述
适配器模式把一个类的接口变换成客户端所期待的另一种接口。
适配器模式使原本无法在一起工作的两个类能够在一起工作。
2.生活中的例子
美国的生活用电压是110伏,而中国的电压是220伏,如果要在中国使用在美国购买的电器,就必须有一个能把220伏电压转换成110伏电压的变压器。
3.适配器模式分类
1)类形式的适配器——使用继承实现适配器模式(is a)
2)实例形式的适配器——使用关联实现适配器模式(has a)
4.类形式的适配器
4.1类形式
目标(Target):就是我们所期待得到的接口。注意,由于这里讨论的是类变压器模式,因此目标不可以是类,而是接口。
源(Adaptee):现有需要适配的接口。
变压器(Adapter):变压器类是本模块的核心。变压器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是实类。
4.2.代码演示
/**
* Target是目标类,也就是需要使用的类型
*/
public interface Target {
/**
* 该方法与源Adaptee中的方法相同
*/
void SampleOperation1();
/**
* 该方法是目标类中的新方法
*/
void SampleOperation2();
}
-----------------------------------------------------------------
/**
* 源类,也就是需要被适配的类
*/
public class Adaptee {
/**
* 模拟源类中的方法
*/
public void SampleOperation1() {
System.out.println("调用Adaptee类中的SampleOperation1方法");
}
}
-----------------------------------------------------------------
/**
* 适配器类Adapter,作用是把Adaptee变成Target
* 实现方法为:Adapter继承Adaptee,实现Target
*/
public class Adapter extends Adaptee implements Target {
/**
* 实现接口Target中的SampleOperation2方法
* SampleOperation1方法直接使用Adaptee中的方法
*/
@Override
public void SampleOperation2() {
System.out.println("调用Adapter类中的SampleOperation2方法");
}
}
----------------------------------------------------------------
//测试类
public class Client {
public static void request(Target t) {
t.SampleOperation1();
t.SampleOperation2();
}
public static void main(String[] args) {
request(new Adapter());
//调用Adaptee类中的SampleOperation1方法
//调用Adapter类中的SampleOperation2方法
}
}
5.实例形式的适配器
5.1实例形式
5.2代码演示
Target.java和Adaptee.java 代码没变化
/**
* 适配器类
*/
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
super();
this.adaptee = adaptee;
}
//直接调用Adaptee类中的SampleOperation1方法
public void SampleOperation1() {
adaptee.SampleOperation1();
}
public void SampleOperation2() {
System.out.println("调用Adapter类中的SampleOpertion2方法");
}
}
四、装饰器模式(Decorator)
1.概述
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类。
2.装饰模式结构
抽象构件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件(ConcreteComponent):定义一个将要接收附加责任的类。
装饰(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator):负责给构件对象“贴上”附件的责任。
3.应用场景:
1)需要扩展一个类的功能,或给一个类增加附加责任。
2)需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
4.代码演示
/**
* 组件类,是准备随时扩展新功能的类型
*/
public interface Component {
void SampleOperation();
}
/**
* 具体组件类,功能将被动态扩展
*/
public class ConcreteComponent implements Component {
public void SampleOperation() {
System.out.println("调用ConcreteComponent具体组件类中的SampleOperation方法");
}
}
/**
* 装饰器类,实现了Component接口,同时关联了Component
*/
public class Decorator implements Component {
private Component component;
public Decorator(Component com) {
this.component = com;
}
public void SampleOperation() {
System.out.println("Decorator装饰器类对SampleOperation方法进行了扩展");
component.SampleOperation();
}
}
/**
* 具体装饰器类,继承了Decorator装饰器类
*/
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void SampleOperation() {
super.SampleOperation();
System.out.println("ConcreteDecorator具体装饰器类对SampleOperation方法进行了扩展");
}
}
/**
* 客户端,用不同的组件对象去调用方法
*/
public class Client{
public static void main(String[] args) {
//创建组件对象component,调用SampleOperation方法
Component component = new ConcreteComponent();
component.SampleOperation();
System.out.println("-----------------分割线----------------");
//使用Decorator装饰组件对象component,调用SampleOperation方法
Component decorator = new Decorator(component);
decorator.SampleOperation();
System.out.println("-----------------分割线----------------");
//使用ConcreteDecorator装饰组件component,调用SampleOperation方法
Component concreteComponent = new ConcreteDecorator(component);
concreteComponent.SampleOperation();
System.out.println("-----------------分割线----------------");
}
}
执行结果:
5.java的I/O中的装饰模式
五.代理模式(Proxy)
1.概述
所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。
在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,进行额外的预处理和后续处理。
2.代理模式的类图
抽象主题角色(Subject):声明了真实主题和代理主题的共同接口,这样在任何可用真实主题的地方都可以使用代理主题。
代理主题角色(Proxy):代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象,代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作。
真实主题角色(RealSubject):定义了代理角色所代表的真实对象。
3.代码演示
/**
* 抽象主题角色,定义了真实主题和代理主题都要实现的方法
*/
public abstract class Subject {
public abstract void request();
}
/**
* 真实主题
*/
public class RealSubject extends Subject {
public RealSubject() {
}
public void request() {
System.out.println("调用真实主题的request方法");
}
}
/**
* 代理主题
*/
public class ProxySubject extends Subject {
//关联真实主题
private RealSubject realSubject;
public void ProxySubject() {
}
//覆盖抽象主题的方法,在对真实主题调用request方法的前后,加上了预处理和后处理
public void request() {
preRequest();
if (realSubject == null) {
realSubject = new RealSubject();
realSubject.request();
}
postRequest();
}
private void preRequest() {
System.out.println("调用代理主题的preRequest方法");
}
private void postRequest() {
System.out.println("调用代理主题的postRequest方法");
}
}
/**
* 客户端
*/
public class Client {
static public void test(Subject subject) {
subject.request();
}
public static void main(String[] args) {
//调用真实主题的request方法
test(new RealSubject());
System.out.println("----------------分割线---------------");
//调用代理主题的request方法
test(new ProxySubject());
}
}
打印结果:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。