工厂模式
工厂模式是java中嘴常用的设计模式之一,在工厂模式中,我们创建对象是不会对客户端暴露创建逻辑,并且是通过使用同一个公共的接口来指向新创建的对象
步骤一
创建一个接口
public interface Shape {
void draw();
}
步骤二
创建实现接口的实体类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
步骤三
创建一个工厂,生成基于给定信息的实体类对象
public class ShapeFactory {
public static class TypeName {
public static final String CIRCLE = "CIRCLE";
public static final String RECTANGLE = "RECTANGLE";
public static final String SQUARE = "SQUARE";
}
public Shape getShape(String shapeType){
if (shapeType == null){
return null;
}
if (shapeType.equals(TypeName.CIRCLE)){
return new Circle();
}
if (shapeType.equals(TypeName.RECTANGLE)){
return new Rectangle();
}
if (shapeType.equals(TypeName.SQUARE)){
return new Square();
}
return null;
}
}
步骤四
使用该工厂,通过传递的类型获取实体类对象
public class TestMain {
public static void main(String[] args) {
final ShapeFactory shapeFactory = new ShapeFactory();
shapeFactory.getShape(ShapeFactory.TypeName.CIRCLE).draw();
shapeFactory.getShape(ShapeFactory.TypeName.RECTANGLE).draw();
shapeFactory.getShape(ShapeFactory.TypeName.SQUARE).draw();
}
}
步骤五
输出结果
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
public class Singleton {
//volatile 防止指令重排序
private volatile static Singleton singleton;
//私有化构造方法
private Singleton(){}
public static Singleton getSingleton(){
if (null == singleton){
synchronized (Singleton.class){
if (null == singleton){
singleton = new Singleton();
}
}
}
return singleton;
}
}
适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
我们通过下面的实例来演示适配器模式的使用。其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4 文件。
步骤一
为媒体播放器和更高级的媒体播放器创建接口
public interface MediaPlayer {
public void play(String audioType, String fileName);
}
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}
步骤二
创建实现了AdvancedMediaPlayer 接口的实现类
public class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: " + fileName);
}
@Override
public void playMp4(String fileName) {
//什么也不做
}
}
public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
//什么也不做
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file . Name: " + fileName);
}
}
步骤三
创建实现了MediaPlayer 接口的适配器类
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMediaPlayer;
public MediaAdapter(String audioType){
if (audioType.equalsIgnoreCase("vlc")){
advancedMediaPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMediaPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")){
advancedMediaPlayer.playVlc(fileName);
}else if (audioType.equalsIgnoreCase("mp4")){
advancedMediaPlayer.playMp4(fileName);
}
}
}
步骤四
创建实现了 MediaPlayer 接口的实体类
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file. Name: " + fileName);
}
//mediaAdapter 提供了播放其他文件格式的支持
else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("Invalid media. format not supported");
}
}
}
步骤五
使用AudioPlayer 来播放不同类型的音频格式
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}
步骤六
输出结果
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file . Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported
装饰者模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
步骤一
创建一个接口:Shape
public interface Shape {
void draw();
}
步骤二
创建实现接口的实体类。
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
步骤三
创建实现了 Shape 接口的抽象装饰类。
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
public void draw() {
decoratedShape.draw();
}
}
步骤四
创建扩展了 ShapeDecorator 类的实体装饰类。
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
步骤五
使用 RedShapeDecorator 来装饰 Shape 对象。
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
步骤六
执行程序,输出结果:
Circle with normal border
Shape: Circle
Circle of red border
Shape: Circle
Rectangle of red border
Shape: Rectangle
代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
步骤一
创建实现接口的实体类
public interface Image {
void display();
}
步骤二
创建实现接口的实体类
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
步骤三
当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
步骤四
执行程序,输出结果:
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg
观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
步骤一
创建 Subject 类。
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
步骤二
创建 Observer 类。
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
步骤三
创建实体观察者类。
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
步骤四
使用 Subject 和实体观察者对象。
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
步骤五
执行程序,输出结果:
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010