设计模式(主要的五种)
1.设计模式:
设计模式就是代码设计经验
2.设计模式的类型:
分为三大类:创建型模式,结构型模式,行为模式
创建型模式:
单例模式:某个类只能有一个实例,提供一个全局的访问点。
工厂模式:一个工厂类根据传入的参数决定创建出那一种产品类的实例。
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
结构型模式
适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
装饰模式:动态的给对象添加新的功能。
代理模式:为其他对象提供一个代理以便控制这个对象的访问。
亨元模式:通过共享技术来有效的支持大量细粒度的对象。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
行为型模式
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
观察者模式:对象间的一对多的依赖关系。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
中介者模式:用一个中介对象来封装一系列的对象交互。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
3.单例模式:
1.一个类只有一个实例
2.只提供一个全局访问点
3.自我实例化( 一个对象在其自身的定义中创建自己的实例 )
懒汉模式在第一次调用时才创建实例,适合节省资源,但需要考虑线程安全问题。
饿汉模式在类加载时就创建实例,确保线程安全,但会占用更多资源,可能在不需要时也会初始化。
饿汉模式1:
很形象,通过getxxx静态方法把静态对象返回出去
这里的对象是私有的,防止外头的人修改,起到保护的作用
返回对象
public class UserMassage {
//这是饿汉模式1
//创建静态对象,自我实例化
public static final UserMassage usermassage = new UserMassage();
//提供全局访问点
public static UserMassage getUsermassage(){
return usermassage;
}
public void show(){
System.out.println("我是单例模式");
}
}
饿汉模式2:
public class UserMassage2 {
//饿汉模式2
public static final UserMassage2 usermassage;
static {
usermassage = new UserMassage2();
}
public void show(){
System.out.println("我是单例模式");
}
}
懒汉模式:
先把静态对象设为null
判断静态对象是否为null
为null则生产一个返回
不为null则用这个对象
public class LayManModel {
//懒汉模式
//私有静态变量保存实例
private static LayManModel layManModel;
//提供公共的获取实例的方法
public static LayManModel getInstance() {
//使用synch保证线程安全
if (layManModel == null) {
synchronized (LayManModel.class) {
if (layManModel == null) {
layManModel = new LayManModel();
}
}
}
return layManModel;
}
public void show () {
System.out.println("我是懒汉模式");
}
}
测试代码:
1.== 用来判断地址从而判断是否是同一个对象
2.通过全局访问点来创建对象
public class Main2 {
public static void main(String[] args) {
LayManModel layManModel1 = LayManModel.getLayManModel();
LayManModel layManModel2 = LayManModel.getLayManModel();
System.out.println(layManModel1 == layManModel2);
layManModel1.show();
}
}
优点:
在内存中只有一个实例,避免频繁的创建和销毁实例
缺点:
没有接口,不能继承
注意事项:getUserMassage() 方法中需要使用同步锁 synchronized (UserMassage.class) 防止多线程
同时进入造成 UserMassage被多次实例化
4.工厂模式:
优点
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定
程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事 。
面条接口:
public interface MianTiao {
//面条抽象类
public abstract void des();
}
三种产品:三种面条
拉面:
public class LaMian implements MianTiao{
@Override
public void des() {
System.out.println("我是拉面,兰州的拉面");
}
}
泡面:
public class PaoMian implements MianTiao{
@Override
public void des() {
System.out.println("我是泡面,大家都不爱吃的泡面");
}
}
烩面:
public class HuiMian implements MianTiao{
@Override
public void des() {
System.out.println("我是烩面,河南人爱吃的烩面");
}
}
测试方法:
public class Main {
//传入我要生产面
public static void main(String[] args) {
MianTiao miantiao = SimpleNoodlesFactory.createNoodles(LA_MIAN);
miantiao.des();
}
}
工厂:
public class SimpleNoodlesFactory {
//简单面条工厂
protected static final int PAO_MIAN = 1;
protected static final int LA_MIAN = 2;
protected static final int HUI_MIAN = 3;
//这个方法是关键,用来生产的
public static MianTiao createNoodles(int type) {
switch (type) {
case PAO_MIAN:
return new PaoMian();
case LA_MIAN:
return new LaMian();
default:
return new HuiMian();
}
}
}
抽象工厂:
因为工厂和工厂不一样,这个是面条工厂,我们随着企业的扩大需要包子工厂,生产工厂的工厂就是抽象工厂,也叫二级工厂。
5.装饰模式:
装饰模式是用来替代继承的一种设计模式。它通过一种无须定义子类的方式来给对象动态增加职责,使
用对象之间的关联关系取代类之间的继承关系。降低了系统的耦合,可以动态的增加或者删除对象的职 责
接口:
public interface Showable {
//展示接口
public abstract void show();
}
装饰器:
public abstract class Decorator implements Showable{
Showable showable ;//持有一个善于展示自己某个家伙
//抽象装饰器
//构造函数
public Decorator(Showable showable){
this.showable = showable;
}
//无需实现因为现在装饰器还不知道如何修饰
public abstract void show();
}
装饰对象:
public class Girl implements Showable{
@Override
public void show() {
System.out.print("女友的素颜");
}
}
装饰功能:
描眉:
public class MiaoMei extends Decorator{
public MiaoMei(Showable showable) {
super(showable);
}
//重写接口化妆后展示 描眉
@Override
public void show() {
System.out.print("描眉(");
showable.show();
System.out.print(")");
}
}
涂口红:
public class TuKouHong extends Decorator{
public TuKouHong(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("涂口红(");
showable.show();
System.out.print(")");
}
}
测试方法:
这个装饰模式就是套的方式
和I/O流中的创建可像
public class Main {
public static void main(String[] args) {
//创建女友对象
Girl girl = new Girl();
//将女友放入描眉类
MiaoMei lyw = new MiaoMei(girl);
TuKouHong cmy = new TuKouHong(lyw);
cmy.show();
}
}
6.代理模式:
代理模式 指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关 业务的处理。
/*
* 定义Network接口
*/
public interface Network {
public void browse(); // 定义浏览的抽象方法
}
/*
* 真实的上网操作
*/
public class Real implements Network {
//重写抽象方法
public void browse() {
System.out.println("上网浏览信息!");
}
}
/*
* 代理上网
*/
public class Proxy implements Network {
private Network network;
// 设置代理的真实操作
public Proxy(Network network) {
this.network = network; // 设置代理的子类
}
// 身份验证操作 其他操作
public void check() {
System.out.println("检查用户是否合法!");
}
//代码实现上网
public void browse() {
this.check(); // 调用具体的代理业务操作
this.network.browse(); // 调用真实的上网操作
}
}
public static void main(String args[]) {
Network net = null; // 定义接口对象
net = new Proxy(new Real()); // 实例化代理,同时传入代理的真实操作
net.browse(); // 调用代理的上网操作
}
7.观察者模式
就是举个例子:订报纸
报纸厂家和订阅报纸的人之间这种一对多的就可以称为观察者模式
报纸厂家是被观察者
订阅报纸的人是观察者
当你订阅了 一份报纸,每天都会有一份最新的报纸送到你手上,有多少人订阅报纸,报社就会发多少份报纸,报社 和订报纸的客户就是上面文章开头所说的“一对多”的依赖关系
奶厂:
接口:
public interface Subject {
//订阅
void attach(Observer observer);
//取消订阅
void detach(Observer observer);
//通知变动
void notifyChanged();
}
实例:
public class RealSubject implements Subject{
//奶厂
//本奶厂下订奶的人集合
private List<Observer> observerList = new ArrayList<Observer>();
//添加订阅者
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
//删除订阅者
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
//消息通知订阅者
@Override
public void notifyChanged() {
for (Observer observer : observerList) {
observer.update();
}
}
}
订牛奶的:
接口:
package ObserverTest;
public interface Observer {
/**
* 接收变动通知
*/
void update();
}
实例:
package ObserverTest;
public class RealObject implements Observer{
//奶厂
@Override
public void update() {
System.out.println("通知");
}
}
测试方法:
public class mainTest {
public static void main(String[] args) {
Subject subject = new RealSubject(); //创建奶厂
Observer observer = new RealObject();//创建订阅人
subject.attach(observer);//订阅人订阅 subject奶厂
subject.notifyChanged();//奶厂发布消息 订阅者接收
}
}
奶厂可以管理订牛奶的,删除,添加或者发布消息
订牛奶的只能接收消息
总结:
通过定义一个抽象接口 Subject(奶厂),我们可以将 奶厂 和 订奶的人 的行为统一起来。