Java设计模式
标签: Java 设计模式
设计模式六大原则
- 单一职责原则
- 开闭原则
- 依赖倒置原则
- 迪米特法则
- 接口隔离原则
- 里氏替换原则
单一职责原则
简述:对功能进行分类,尽量实现一个类之负责一个功能。
例子:人吃饭。人 和 饭分别为类,人拥有吃的能力。
作用:编程上要使用到单一职责,做到职责分离,更大程度的达到代码复用,使系统的设计更加灵活,易维护。
开闭原则
简述:类,函数,属性对扩展开放,对修改关闭。
例子:当我们因部分原因需要对原有代码进行修改时,可能会给那些引入旧代码的部分出现错误,也可能会使我们不得不重构整个功能,并且需要原有代码进行测试,需要开闭原则来解决这种问题。
依赖倒置原则
简述:抽象不依赖细节,细节依赖于抽象,也就是面向接口编程。
例子:内存条和硬盘都是面向接口设计的,如果是面向细节的话增加内存条或硬盘可能就需要换主板了。
迪米特法则
简述:一个对象应该对其他对象尽少了解,不需要知道它内部是如何复杂实现的。调用者只需要知道他需要的方法即可。尽量减少耦合度。
耦合度越大当一个类发生改变时,对另一个类的影响也越大。
例子:使用框架时,开发者都会抽出一个类供使用者调用,而这个类像中介一样去调用其他的类。
接口隔离原则
简述:在定义接口方法的时候尽量追求简单,避免接口臃肿。
例子:在开发过程中,为了节省时间可能会将很多功能抽象成接口,这样并不对,需要合理的拆分接口的方法,另外抽取一个独立的接口,避免原有的接口臃肿导致代码难以理解。
里氏替换原则
简述:在继承类时,除了扩展新的功能外,尽量不要删除或修改对父类方法的引用,也尽量不要重载父类的方法。
例子:每个类都是Object的子类,Object中有个toString()的方法。若子类重写此方法并返回Null,这个类的下一级继承也返回Null,不同开发人员维护时考虑不到此问题,很可能导致程序崩溃。
设计模式
单例模式
单例模式即一个类只有一个实例的存在。
饿汉模式
在小明年轻时,电视机还没被普及,那时他非常想看电视,恰巧他邻居是个大土豪,买了高清蓝光4K钛合金电视,于是小明就去土豪家,然而小明的邻居都在土豪家。土豪说:我先看,我看完新闻联播了。你们再决定来看什么。
private static TV tv = new TV(); //首先,土豪买了个电视机
private TV(){
} //因为土豪的,所以是private
public static TV getTV(){
//土豪看困了,让下个人看。
return tv;
}
那个时候电视机只有一个,大家都想看,这种就叫做饿汉单例模式。
懒汉模式
后来,小明另一个邻居老王家也买了电视,老王早就过了看电视的年龄,电视放在那。
private TV(){
}
private static Tv tv;
小明觉得不看太可惜了,就去老王家看,老王很大方,随便看吧
public static TV getTV(){
if(tv==null){
tv = new TV();
}
return tv;
}
这种想看就开电视看,随便看的模式叫懒汉模式。
双重检验锁
最近老王家买了电脑,小明天天去玩,而他表弟听说后也随风而来。当小明玩的时候,老王很仗义的告诉他表弟说电脑锁忘了,想起来告诉他。
//所有的写(write)操作都将发生在读(read)操作之前。
private volatile static Computer computer;
public static Computer getComputer(){
if(computer==null){
synchronized(Computer.class){
//保证了同一时间只能只能有一个对象访问此同步块
if(computer==null){
computer = new Computer();
}
}
}
return computer;
}
这就是所谓的双重检验锁。
工厂模式
在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式
小明家附近有个老面馆。提供三种面条贩卖。
//面条接口
public interface Noodle{
void desc(); //面条描述方法
}
//拉面类
public class HandPulledNoodle implements Noodle{
public void desc(){
System.out.println("好吃的拉面");
}
}
//方便面
public class InstantNoodle implements Noodle{
public void desc(){
System.out.println("康师傅方便面");
}
}
//干扣面
public DryBuckleSurface implements Noodle{
public void desc(){
System.out.println("辣味十足的干扣面");
}
}
面馆里有个拉面师傅,告诉他你想吃的面,他就给你做
//拉面师傅
public Cook{
public static Noodle createNoodle(int type){
switch(type){
case 0:
return new HandPulledNoodle();
case 1:
return new InstantNoodle();
case 2:
return new DryBuckleSurface();
default:
return new DryBuckleSurface();
}
}
}
小明想吃家乡的干扣面便告诉师傅.
public class Ming{
public static void main(String[] args){
Noodle noodle = Cook.createNoodle(2);
noodle.desc();
}
}
工厂方法模式
上述模式不适用解耦,若再增加需求就需要改动原有代码,并不建议,所以如下提供工厂方法模式。
从前有个皇帝。他叫小明,特爱干净每天都要换衣服,所以让每个宫女负责一种衣服。需要的时候叫宫女去做。
//衣服接口
public interface Dress{
//衣服描述
void desc();
}
//衣服具体实现
public class RedDress{
public void desc(){
System.out.println("红衬衫");
}
}
public class GreenDress{
public void desc(){
System.out.println("绿衬衫");
}
}
//宫女接口
public interface MaidInWaiting{
Dress createDress();
}
//宫女的具体实现,负责红色衣服
public class RedLadyInWaiting implements MaidInWaiting{
public static Dress createDress(){
return new RedDress();
}
}
//宫女的具体实现,负责绿色衣服
public class GreenLadyInWaiting implements MaidInWaiting{
public static Dress createDress(){
return new GreenDress();
}
}
小明想穿红色衣服
public class Main{
public static void main(String[] args){
MaidInWaiting wait = new RedLadyInWaiting();
Dress dress = wait.createDress();
dress.desc();
}
}
抽象工厂模式
所谓抽象工厂模式即,包含以下类:
多个抽象工厂类
多个抽象工厂实现类
多个抽象产品类
多个抽象产品实现类
//怪物抽象工厂
public interface MasterFactory{
Master createMaster();
}
//管道抽象工厂
public interface PipelineFactory{
Pipeline createPipeline();
}
//乌龟怪物工厂实现类
public class TortoiseFactory implements MasterFactory{
public Master createMaster(){
return new Tortoise();
}
}
//魔鬼怪物工厂实现类
public class DevilFactory implements MasterFactory{
public Master createMaster(){
return new Devil();
}
}
//管道工厂实现类
public class IPipelineFactory implement PipelineFactory{
public Pipeline createPipeline(){
return new IPipeline();
}
}
//怪物抽象类
public interface Master{
void move();
}
//管道抽象类
public interface Pipeline{
void desc();
}
//管道实现类
public class IPipeline implement Pipeline{
public void desc(){
System.out.println("绿色管道");
}
}
//怪物实现类 乌龟
public class Tortoise implements Master{
public void move(){
System.out.println("缓慢移动");
}
}
//怪物实现类 魔鬼
public class Devil implements Master{
public void move(){
System.out.println("飞行移动");
}
}
public class Main{
public static void main(String[] args){
MasterFactory tf = new TortoiseFactory();
Master tortoise = tf.createMaster();
tortoise.move();
}
}
策略模式
一、策略模式定义
定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略 模式可以在不影响客户端的情况下发生变化。
二、策略模式涉及到的三个角色
环境(Context)角色 持有一个Strategy的引用
抽象策略(Strategy)角色 这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色 包装了具体的算法或行为。
举个例子吧
//腾讯客服招待方式抽象接口
public interface Treat{
void say();
}
//机器人客服
public class RobotTreat implements Treat{
public void say(){
System.out.println("你好,我是小强机器人,很高兴为你服务");
}
}
public class Person implements Treat{
public void say(){
System.out.println("尊贵的心悦会员您好,我是您的专用客服,很高兴为您服务!");
}
}
public class Context{
private Treat treat;
public Context(Treat treat){
this.treat = treat;
}
public void setTreat(Treat treat){
this.treat = treat;
}
public void say(){
treat.say();
}
}
public class Main{
public static void main(String[] args){
//对待不同的用户调用不同的策略来进行处理
//普通用户
Context context = new Context(new RobotTreat());
context.say();
//心悦会员
context.setTreat(new Person());
context.say();
}
}
装饰者模式
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
设计原则:
- 多用组合,少用继承。
- 类应设计的对扩展开放,对修改关闭。
//狼接口 被装饰接口
interface Wolf{
public abstract void display();
}
//被装饰类 灰太狼
class Wolffy implements Wolf{
@Override
public void display() {
System.out.println("灰太狼正在准备食材");
}
}
//装饰者类A 红太狼 内部维护一只狼
class Hollie implements Wolf{
private Wolf wolf;
public Hollie(Wolf wolf) {
this.wolf = wolf; }
@Override
public void display() {
System.out.println("红太狼正在烧水准备煮羊");
wolf.display();
}
}
//装饰者类B 小灰灰狼 内部维护一只狼
class Howie implements Wolf{
private Wolf wolf;
public Howie(Wolf wolf){
this.wolf = wolf; }
@Override
public void display() {
wolf.display();
System.out.println("小灰灰放走了小羊们");
}
}
//测试类
public class DeckerDemo {
public static void main(String[] args) {
Wolf wolffy = new Wolffy();
Wolf hollie = new Hollie(wolffy);
Wolf howie = new Howie(hollie);
howie.display();
}
}
观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
- 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
public class LookerDemo {
public static void main(String[] args) {
Potence ming = new Team("小明");
Potence zang = new Team("小张");
Potence liang = new Team("小亮");
Potence hua = new Team("小花");
Tyfon.addTeam(ming);
Tyfon.addTeam(zang);
Tyfon.addTeam(liang);
Tyfon.addTeam(hua);
ming.removePerson(hua);
ming.removePerson(liang);
ming.removePerson(zang);
}
}
//大喇叭消息发送中心
class Tyfon{
private static List<Potence> potences = new ArrayList<>();
//添加参赛人员
public static void addTeam(Potence potence){
potences.add(potence);
}
//向参赛人员发送消息
public static void sendMessage(String msg){
for (Potence p : potences) {
p.update(msg);
}
System.out.println("剩余参赛人员:"+potences);
}
//删除参加人员
public static void remove(Potence potence){
potences.remove(potence);
}
}
//消息接收器
abstract class Potence{
//参赛人员
protected String name;
public String getName() {
return name;
}
public Potence(String name){
this.name = name;
}
//接受消息
abstract void update(String msg);
//干掉其他参赛人员
abstract void removePerson(Potence potence);
}
class Team extends Potence{
public Team(String name){
super(name);
}
@Override
public void update(String msg) {
System.out.println(name+"收到消息: "+msg);
}
@Override
public void removePerson(Potence potence) {
Tyfon.remove(potence)