常用的设计模式
- 有哪些常见的设计模式:
- 单例模式:
- 工厂模式:
- builder模式:
- MVC模式
- 适配器模式:
- 观察者模式:
1.有哪些常见的设计模式:
在这里给出六种常见的设计模式,分别是:
单例模式,工厂模式,builder模式,MVC模式,适配器模式,观察者模式
2.单例模式
单例模式是软件设计的一种常用的设计模式, 在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
eg:
在一个student类中,一个大学可以有很多的学生(可以用几万人),但是却只有一个校长,也就是说任何一个学生中,校长这个对象都应该是独一无二的,这就用到了单例模式.
注意:
-
单例类只能有一个实例
-
单例类的构造方法必须是是私有的(不能实例化对象)
-
单例类必须自己创建自己的唯一实例
-
单例类必须给所有其他的类提供实例
-
主要解决的问题:一个全局使用的类频繁的被创建和销毁
优点:
- 在内存中只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
- 避免对资源的多重利用
缺点:
- 没有接口,不能继承
- 与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
如何实现单例模式:
1.通过类加载时实现:
package NewText;
public class Singleton {
//类加载时直接创建实例
static Singleton instance = new Singleton();
private Singleton() {
}
//该类的构造方法是私有的,不可以创建实例
public static synchronized Singleton getinstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
}
}
运行结果:
2.每次在调用时创建实例:
package NewText;
public class Singleton {
static Singleton instance ;
private Singleton() {
}
/**
* 通过每次调用方法时创建实例
* (判断实例是否被创建)若已经创建则直接返回,若没有创建则创建新的
* @return
*/
public static synchronized Singleton getinstance(){
if(instance==null) {
instance = new Singleton();
}
return instance;
}
public static void main(String[] args) {
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
}
}
运行结果:
3,通过静态内部类实现类加载时创建实例:
package NewText;
public class Singleton {
static Singleton instance ;
private Singleton() {
}
public static Singleton getinstance(){
return Holder.instance;
}
/**
* 通过使用静态内部类来实现创建实例
* @author Bug研发工程师
*
*/
static class Holder{
static Singleton instance = new Singleton();
}
public static void main(String[] args) {
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
System.out.println(Singleton.getinstance());
}
}
运行结果:
工厂模式:
什么是工厂模式:
工厂模式正如其名字一样,是一个工厂,也就是说用户只需要提供原材料,而不需关心内部的具体实现(逻辑)
举个栗子:
您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
优点:
- 一个调用者创建一个对象,只需要知道名称即可
- 扩展性高,如果想要增加一个产品,只需要增加一个工厂类即可
- 屏蔽产品的具体实现,只关心产品的接口
实现方式:
-
创建不同种类产品的接口
-
创建相关的产品类实现相关的接口
-
创建一个工厂类,根据不同的名称调用不同的产品类的实现,返回创建结果
上面图片说明了,每一个产品类都实现了shape接口,当用户想要创建一个产品时通过调用工厂方法,再由工厂去安排创建产品(由子类实现),将创建好的产品返回给用户.
具体实现:
使用枚举类型,以免用户选择错误
package NewText;
public enum TYPE{
CIRCLE,SQUARE,RECT
}
创建形状接口
package NewText;
public interface Shape {
public void draw();
}
创建子类的具体实现(圆形)
package NewText;
public class Circle implements Shape{
@Override
public void draw() {
System.out.println("正在画圆");
}
}
矩形
package NewText;
public class Rect implements Shape{
@Override
public void draw() {
System.out.println("正在画矩形");
}
}
方形
package NewText;
public class Rect implements Shape{
@Override
public void draw() {
System.out.println("正在画矩形");
}
}
主类测试工厂模式
package NewText;
public class Rect implements Shape{
@Override
public void draw() {
System.out.println("正在画矩形");
}
}
builder模式:
什么是builder模式呢
使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
例如:
相比大家都应该吃过烤冷面把,可以加蛋,可以加里脊,加肉松,加火腿,等等,那么如果我想要自由的组合这些产品,就要使用到builder模式
实现方式:
-
首先将构造方法私有化,不许创建实例
-
然后使用静态内部类Builder来创建Builder对象
-
通过调用Buider中的build方法,将Builder对象的属性赋值给User对象(先创建User对象)
-
最后返回build方法创建好的User对象
package cn.csuftacm.poorguy.poorguy;
public class User {
String name;
String id;
String age;
String address;
private User() {
}
@Override
public String toString() {
String string = name+" "+age+" "+id+" "+address+"\n";
return string;
}
public static class builder{
String name;
String id;
String age;
String address;
public builder setName(String name) {
this.name = name;
return this;
}
public builder setId(String id) {
this.id = id;
return this;
}
public builder setAge(String age) {
this.age = age;
return this;
}
public builder setAddress(String address) {
this.address = address;
return this;
}
public User build() {
User user = new User();
user.name = name;
user.age = age;
user.id = id;
user.address = address;
return user;
}
}
public static void main(String[] args) {
User u1 = new User.builder()
.setName("PoorGuy")
.setAddress("CSUFT")
.setId("666666").build();
User u2 = new User.builder()
.setName("Bug研发工程师")
.setAddress("CSUFT")
.setAge("18")
.setId("777777").build();
System.out.println(u1);
System.out.println(u2);
}
}
运行结果:
MVC模式:
什么是MVC模式呢
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
通俗一点讲就是将视图和逻辑分离
model(模型):代表一个存储数据的对象,也可以带有逻辑和更新
view(视图);数据的可视化(可以是web界面,也可以是窗口界面)
Controller(控制器): - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离
细节实现:
-
首先创建模型,用于写逻辑或者数据的存储
-
设计页面,页面中不含有任何model对象
-
创建Callback接口,使用接口回调
-
让Controller实现Callback接口,实现模型和视图之间的数据流动,信息传输
写一个简单的例子:
package cn.csuftacm.poorguy.poorguy;
public class App {
public static void main(String[] args) {
Model model = new Model();
Control c = new Control(model);
view view = new view();
}
}
控制器的编写:
package cn.csuftacm.poorguy.poorguy;
import cn.csuftacm.poorguy.poorguy.view.Callback;
/**
* 把视图和模型做连接
*
* @author Bug研发工程师
*
*/
public class Control implements Callback{
Model model = new Model();
public Control(Model model) {
this.model = model;
}
public Control() {
}
public void setInput(int height) {
model.set(height);
}
public double showMaleWeight() {
return model.getMale();
}
public double showFmaleWeight() {
return model.getFamal();
}
}
model的编写:
package cn.csuftacm.poorguy.poorguy;
public class Model {
private int height;
public void set(int height) {
this.height = height;
}
public double getFamal() {
return height * 0.9;
}
public double getMale() {
return height * 0.8;
}
}
view和callback接口的实现:
package cn.csuftacm.poorguy.poorguy;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class view extends JFrame {
Control control = new Control();
int height = 480;
int width = 320;
String title = "标准体重计算器";
JTextField input = new JTextField();
JButton buttonFamal = new JButton();
JButton buttonmal = new JButton();
JLabel label = new JLabel();
public void setControl(Control control) {
this.control = control;
}
public view() {
setSize(width, height);
setTitle(title);
setResizable(true);
setResizable(false);
initView();
setVisible(true);
}
private void initView() {
input = new JTextField();
buttonFamal = new JButton("男士");
buttonmal = new JButton("女士");
label = new JLabel();
getContentPane().add(input, BorderLayout.NORTH);
getContentPane().add(buttonmal, BorderLayout.WEST);
getContentPane().add(buttonFamal, BorderLayout.EAST);
getContentPane().add(label, BorderLayout.CENTER);
BtListener listener = new BtListener();
buttonFamal.addActionListener(listener);
buttonFamal.setActionCommand("F");
buttonmal.addActionListener(listener);
buttonmal.setActionCommand("M");
}
class BtListener implements ActionListener{
Control callback = control;
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
String input1 = input.getText();
callback.setInput(Integer.parseInt(input1));
if(command.equals("F")) {
label.setText(String.valueOf(callback.showFmaleWeight()));
}else {
label.setText(String.valueOf(callback.showFmaleWeight()));
}
}
}
public interface Callback{
void setInput(int height);
double showMaleWeight();
double showFmaleWeight();
}
}
运行结果;
上面只是最简单的一个例子,可以尝试写一下计算器的实现,界面与逻辑分离,并且逻辑部分采用手写大数加法减法等;
适配器模式:
什么是适配器模式呢:
想到适配器,我们第一个想到的就应该是手机(或电脑)电源适配器了把,手机电源适配器的功能就是将220V电压与15V电压相适应,这就是适配器的作用,就是将不同类型的相互适配.
最常用的是监听器接口:
Eg:
我们都使用过的鼠标监听器,其中有很多个方法,我们知道只要实现一个类只要实现一个接口就必须重写接口中的所有方法,那儿可能我们只会用到其中的一个方法或者两个方法,这是就用到了适配器模式.
优点:
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度灵活性好。
缺点:
- 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
- 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
-
创建一个接口
-
使用一个抽象类去实现接口
-
再用我们要使用的类来继承抽象类,这时只需要重写我们需要使用的方法即可.
如下,MouseAdapter为鼠标监听事件的适配器
import java.awt.event.MouseAdapter;
public class Text {
MouseAdapter listener = new MouseAdapter() {
};
}
观察者模式:
什么是观察者模式呢:
当对象存在一对多的关系时,采用观察者模式
比如:当一个对象被更改的时候,会主动去通知它的依赖的对象,观察者模式属于行为型模式.
优点:
-
观察者和被观察者是抽象耦合的。
-
建立一套触发机制。
缺点:
-
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
-
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
-
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
实现过程:
-
创建一个被观察者实现Observable接口
-
创建一个或多个观察者实现Observer接口
-
重写观察者中的update方法
-
当被观察者修改时会主动调用观察者的update方法
注:
在被观察者将要修改的方法中添加setChanged方法来设置当前状态,使用notifyobservers方法来为被观察者添加观察者
App类
package cn.csuftacm.poorguy.app;
public class App {
public static void main(String[] args) {
Data data = new Data();
UI ui = new UI();
Mobel b = new Mobel();
//添加一些观察者
data.addObserver(ui);
data.addObserver(b);
//状态改变
data.setF(36);
//data.setF(69);
}
}
被观察者:
package cn.csuftacm.poorguy.app;
import java.util.Observable;
public class Data extends Observable{
double f;
public void setF(double f) {
this.f = f;
//设置状态为以改变
setChanged();
//通知观察者
//notifyObservers();
//通知观察者
notifyObservers(f);
}
public double getF() {
return f;
}
}
观察者:
package cn.csuftacm.poorguy.app;
import java.util.Observable;
import java.util.Observer;
public class UI implements Observer {
public void display() {
System.out.println("UI 显示更新");
}
@Override
public void update(Observable o, Object arg) {
display();
System.out.println("update" + arg);
}
}
运行结果:
注:观察者模式一般被观察的对象为数据
小白创作,大佬勿喷