总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
实现:1、一个抽象接口Shape
;2、若干实现了抽象接口的实体类Square
, Circle
;3、一个工厂类ShapeFactory
包含创建实体类的方法 getShape()
;4、一个Demo
使用工厂类创建实体对象并执行对应方法
//1、一个抽象接口`Shape`;
public interface Shape {
void draw();
}
//2、若干实现了抽象接口的实体类`Square`, `Circle`;
class Circle implements Shape{
@Override
public void draw() {
System.out.println("画一个圆");
}
}
class Square implements Shape{
@Override
public void draw() {
System.out.println("画一个方");
}
}
//3、一个工厂类`ShapeFactory`包含创建实体类的方法 `getShape()`;
class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String type){
if(type == null){
return null;
}
if("circle".equals(type)){
return new Circle();
} else if ("square".equals(type)) {
return new Square();
}else{
return null;
}
}
}
//4、一个Demo使用工厂类创建实体对象并执行对应方法
public class Demo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape circle = shapeFactory.getShape("circle");
circle.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape square = shapeFactory.getShape("square");
square.draw();
}
}
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
实现:1、一个单例类,其中包含一个该类的静态实例对象,私有的构造函数,一个静态方法获取实例对象,若干实例方法;2、一个Main
获取单例对象并验证。
class SingleObject{
private static SingleObject singleObject = new SingleObject();
private SingleObject(){
}
//让构造函数为 private,这样该类就不会被实例化
public static SingleObject getInstance(){
return singleObject;
}
//获取唯一可用的对象
public void show(){
System.out.println("这是单例对象");
}
}
public class Main{
public static void main (String[] args){
SingleObject object = SingleObject.getInstance();
object.show();
}
}
在工厂模式基础上,给工厂对象提取一个公共抽象父类,根据用户需求创建对应点工厂类实例,然后使用该工厂实例产生对应点类实例。
interface Shape{
void draw();
}
class Circle implements Shape{
public void draw(){
System.out.println("圆形");
}
}
class Square implements Shape{
public void draw(){
System.out.println("方形");
}
}
interface Color{
void fill();
}
class Red implements Color{
public void fill(){
System.out.println("红色");
}
}
class Blue implements Color{
public void fill(){
System.out.println("蓝色");
}
}
abstract class AbstractFactory{
public abstract Shape getShape(String Shape);
public abstract Color getColor(String Color);
}
class ShapeFactory extends AbstractFactory{
public Shape getShape(String shape){
if(shape.equals("circle")){
return new Circle();
}else if(shape.equals("square")){
return new Square();
}else{
return null;
}
}
public Color getColor(String color){
return null;
}
}
class ColorFactory extends AbstractFactory{
public Shape getShape(String shape){
return null;
}
public Color getColor(String color){
if(color.equals("red")){
return new Red();
}else if(color.equals("blue")){
return new Blue();
}else{
return null;
}
}
}
class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
} else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
public class Main{
public static void main (String[] args){
AbstractFactory factory1 = FactoryProducer.getFactory("SHAPE");
Shape shape1 = factory1.getShape("circle");
shape1.draw();
Shape shape2 = factory1.getShape("square");
shape2.draw();
AbstractFactory factory2 = FactoryProducer.getFactory("COLOR");
Color color1 = factory2.getColor("red");
color1.fill();
Color color2 = factory2.getColor("blue");
color2.fill();
}
}
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。
缺点: 1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
示例:音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp3 文件。
实现:1、一个MediaPlayer
接口(目标);2、一个实现MediaPlayer接口的适配器MediaAdapter
;3、适配器接口AdvancedMediaPlayer
和实现类VlcPlayer
;4、Main方法调用适配器播放
interface MediaPlayer{
void play(String type,String song);
}
interface AdvancedMediaPlayer {
public void playVlc(String fileName);
}
class VlcPlayer implements AdvancedMediaPlayer{
public void playVlc(String song) {
System.out.println("Playing vlc file. Name: "+ song);
}
}
class MediaAdapter implements MediaPlayer{
private AdvancedMediaPlayer advancedMediaPlayer;
public void play(String type,String song) {
if(type.equals("mp3")) {
System.out.println("Playing mp3 file. Name: " + song);
//mediaAdapter 提供了播放其他文件格式的支持
}else if(type.equals("vlc")){
advancedMediaPlayer = new VlcPlayer();
advancedMediaPlayer.playVlc(song);
}else{
System.out.println("输入格式有误");
}
}
}
public class Main {
public static void main(String[] args) {
MediaAdapter audioPlayer = new MediaAdapter();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("mp4", "alone.mp4");
}
}