大家好,欢迎来到IT知识分享网。
常用的七种设计模式:单例模式、工厂方法模式、抽象工厂模式、代理模式、装饰器模式、观察者模式和责任链模式。
设计模式分类
设计模式根据工作的目的,分为创建型模式、结构型模式和行为型模式三类。
创建型模式:单例模式、工厂方法模式、抽象工厂模式、创建者模式、原型模式。
结构型模式:适配器模式、代理模式、装饰器模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
软件设计七大原则(OOP原则)
实际上,七大原则的目的只有一个:降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性。
1、单例模式:一个类只有一个实例,且该类能自行创建这个实例的一种模式
①单例类只有一个实例对象
②该单例对象必须由单例类自行创建
③单例类对外提供一个访问该单例的全局访问点
饿汉式单例:类一旦加载就创建一个单例,保证在调用getInstance方法之前单例已经存在,这种饿汉式单例会造成空间浪费。
public class Hungry {
private Hungry(){
} private final static Hungry HUNGRY = new Hungry(); public static Hungry getInstance(){
return HUNGRY; } }
懒汉式单例:为了避免内存空间浪费,采用懒汉式单例,即用到该单例对象的时候再创建。
public class LazyMan {
private LazyMan(){
}; public static LazyMan lazyMan; public static LazyMan getInstance(){
if (lazyMan==null){
lazyMan = new LazyMan(); } return lazyMan; } }
这是最简单的懒汉式,但是,存在很大问题,单线程下这段代码没有问题,但是在多线程下有很大问题。
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName()+""); } public static LazyMan lazyMan; public static LazyMan getInstance(){
if (lazyMan==null){
lazyMan = new LazyMan(); } return lazyMan; } public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(()->{
lazyMan.getInstance(); }).start(); } } }
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName()+""); } public static LazyMan lazyMan; public static LazyMan getInstance(){
if (lazyMan==null){
//第一层检查,检查是否有引用指向对象,高并发情况下会有多个线程同时进入 synchronized (LazyMan.class){
//第一层锁,保证只有一个线程进入 //双重检查,防止多个线程同时进入第一层检查(因单例模式只允许存在一个对象,故在创建对象之前无引用指向对象,所有线程均可进入第一层检查) //当某一线程获得锁创建一个LazyMan对象时,即已有引用指向对象,lazyMan不为空,从而保证只会创建一个对象 //假设没有第二层检查,那么第一个线程创建完对象释放锁后,后面进入对象也会创建对象,会产生多个对象 if(lazyMan==null){
//第二层检查 //synchronized关键字作用为禁止指令重排,保证返回Singleton对象一定在创建对象后 lazyMan = new LazyMan(); //这行代码存在的问题,不能保证原子性 实际上会执行以下内容: //(1)在堆上开辟空间;(2)属性初始化;(3)引用指向对象 //假设以上三个内容为三条单独指令,因指令重排可能会导致执行顺序为1->3->2(正常为1->2->3),当单例模式中存在普通变量需要在构造方法中进行初始化操作时,单线程情况下,顺序重排没有影响;但在多线程情况下,假如线程1执行lazyMan = new LazyMan()语句时先1再3,由于系统调度线程2的原因没来得及执行步骤2,但此时已有引用指向对象也就是lazyMan!=null,故线程2在第一次检查时不满足条件直接返回lazyMan,此时lazyMan为null //synchronized关键字可保证lazyMan = new LazyMan()语句执行顺序为123,因其为非原子性依旧可能存在系统调度问题(即执行步骤时被打断),但能确保的是只要lazyMan!=0,就表明一定执行了属性初始化操作;而若在步骤3之前被打断,此时lazyMan依旧为null,其他线程可进入第一层检查向下执行创建对象 } } } return lazyMan; } public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(()->{
lazyMan.getInstance(); }).start(); } } }
可以看到结果都是只有一个,按理来说是没有问题,实际上不是,上述标注行代码存在问题的,不是一个原子性操作。
静态内部类单例:是不安全,存在问题的,是不安全,存在问题的(修改过的懒汉式单例也是如此)。
public class Inner {
private Inner(){
} public static Inner getInstance(){
return InnerClass.INNER; } public static class InnerClass{
private static final Inner INNER = new Inner(); } }
2、工厂方法模式:实例化对象不是用new,用工厂方法替代。将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。
简单工厂模式:用来生产同一等级架构中的任意产品(对于增加新的产品,需要修改已有代码)
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例。
接下来创建一个接口,两个实现类,一个工厂,一个测试类
//创建手机接口 public interface Phone {
void name(); } //创建华为实现类 public class HuaWei implements Phone{
@Override public void name() {
System.out.println("华为手机"); } } //创建小米实现类 public class XiaoMi implements Phone{
@Override public void name() {
System.out.println("小米手机"); } } //创建工厂 public class PhoneFactory {
public static Phone getPhone(String phone){
if(phone.equals("华为")){
return new HuaWei(); }else if(phone.equals("小米")){
return new XiaoMi(); }else {
return null; } } } //测试类 public class Consumer {
public static void main(String[] args) {
Phone p1= PhoneFactory.getPhone("华为"); Phone p2= PhoneFactory.getPhone("小米"); p1.name(); p2.name(); } }
得到测试结果
华为手机 小米手机
我们通过创建一个PhoneFactory类,成功的完成工厂的创建。我们在创建对象时,也就不需要直接创建对象,而是可以通过创建工厂,这样大大的降低了代码的耦合性。但是,静态工厂模式是不能添加数据的。比如说,我们想添加一个“Oppo”手机类,你不直接修改PhoneFactory工厂代码,是不能实现的。所以,就有了第二种的工厂方法模式。
工厂方法模式:用来生产同一等级架构中的固定产品,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。(支持增加任意产品)
//创建手机接口 public interface Phone {
void name(); } //创建华为实现类 public class HuaWei implements Phone{
@Override public void name() {
System.out.println("华为手机"); } } //创建手机工厂接口 public interface PhoneFactory {
Phone getPhone(); } //创建华为工厂 public class HuaWeiFactory implements PhoneFactory{
@Override public Phone getPhone() {
return new HuaWei(); } } //测试类 public class Consumer {
public static void main(String[] args) {
Phone phone = new HuaWeiFactory().getPhone(); phone.name(); } }
得到测试结果
华为手机
我们创建了手机工厂接口PhoneFactory,再创建华为工厂HuaWeiFactory实现工厂,这样就可以通过HuaWeiFactory创建对象。增加新的具体工厂和产品族很方便,比如说,我们想要增加小米,只需要创建一个小米工厂XiaoMiFactory实现手机工厂接口PhoneFactory,合理的解决的简单工厂模式不能修改代码的缺点。但是,在现实使用中,简单工厂模式占绝大多数。
简单工厂模式与工厂方法模式比较:
3、抽象工厂模式:抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类(围绕一个超级工厂创建其他工厂,该超级工厂称为工厂的工厂)
抽象工厂模式得主要角色:
//电脑接口 public interface Computer {
void play(); void watch(); } //创建华为电脑对象 public class HuaWeiComputer implements Computer{
@Override public void play() {
System.out.println("HuaWei's play!"); } @Override public void watch() {
System.out.println("HuaWei's watch!"); } } //手机接口 public interface Phone {
void send(); void call(); } //创建华为手机对象 public class HuaWeiPhone implements Phone{
@Override public void send() {
System.out.println("HuaWei's send"); } @Override public void call() {
System.out.println("HuaWei's call"); } } //抽象工厂 public interface IProductFactory {
//生产手机 Phone phone(); //生产电脑 Computer computer(); } //创建华为工厂 public class HuaWeiFactory implements IProductFactory{
@Override public Phone phone() {
return new HuaWeiPhone(); } @Override public Computer computer() {
return new HuaWeiComputer(); } } //测试类 public class Consumer {
public static void main(String[] args) {
HuaWeiFactory huaWeiFactory = new HuaWeiFactory(); Phone phone = huaWeiFactory.phone(); phone.call(); phone.send(); Computer computer = huaWeiFactory.computer(); computer.play(); computer.watch(); } }
得到测试结果
HuaWei's call HuaWei's send HuaWei's play! HuaWei's watch!
1、抽象角色:一般会使用接口或抽象类来解决
2、真实角色:被代理的角色
3、代理角色:代理真实角色,代理真实角色后我们会进行一些附属操作
4、访问角色:访问代理对象的人
//租房 public interface Rent {
void rent(); } //房东 public class Master implements Rent{
@Override public void rent() {
System.out.println("Master rent"); } } //中介 public class Proxy implements Rent{
private Master master; public Proxy() {
} public Proxy(Master master) {
this.master = master; } @Override public void rent() {
see(); master.rent(); fare(); } //看房 public void see(){
System.out.println("see"); } //收费 public void fare(){
System.out.println("fare"); } } //测试类 public class Consumer {
public static void main(String[] args) {
Master master = new Master(); //进行代理 Proxy proxy = new Proxy(master); //不需要通过对象,直接通过代理完成响应业务 proxy.rent(); } }
得到测试结果
see Master rent fare
动态代理模式:虽然静态代理模式可以很好的解决开闭原则,但是每有一个真实角色就会产生一个代理,代码量翻倍过于臃肿,开发效率较低。因此,我们就使用动态代理模式进行设计。
//接口 public interface IUserService {
void add(); void delete(); void update(); void query(); } //实现类 public class UserServiceImpl implements IUserService {
@Override public void add() {
System.out.println("add"); } @Override public void delete() {
System.out.println("delete"); } @Override public void update() {
System.out.println("update"); } @Override public void query() {
System.out.println("query"); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //自动生成动态代理类模板 public class ProxyInvocationHandler implements InvocationHandler {
//被代理接口 private Object target; public void setTarget(Object target) {
this.target = target; } //得到代理类 public Object getProxy() {
return Proxy.newProxyInstance(getClass().getClassLoader(), target.getClass().getInterfaces(), this); } public void log(String s) {
System.out.println("[debug]:" + s); } //得到代理类 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName()); Object result = method.invoke(target, args); return result; } } //测试类 public class Consumer {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl(); ProxyInvocationHandler handler = new ProxyInvocationHandler(); //设置代理对象 handler.setTarget(userService); //生成代理类 IUserService proxy = (IUserService)handler.getProxy(); proxy.add(); proxy.query(); } }
得到测试结果
[debug]:add add [debug]:query query
角色分析:
//定义抽象类 public abstract class Drink {
public abstract double cost(); } //定义两个抽象类的实现类 public class Juice extends Drink{
@Override public double cost() {
System.out.println("juice: "+16); return 16; } } public class Milk extends Drink{
@Override public double cost() {
System.out.println("milk: "+12); return 12; } } //定义装饰抽象类 public abstract class Decorator extends Drink {
public abstract double cost(); } //定义两个装饰具体实现类 public class Chocolate extends Decorator{
private final static double COST = 4; private Drink drink; public Chocolate(Drink drink) {
this.drink = drink; } @Override public double cost() {
System.out.println("chocolate:"+4); return COST+drink.cost(); } } public class Pudding extends Decorator{
private final static double COST = 5; private Drink drink; public Pudding(Drink drink) {
this.drink = drink; } @Override public double cost() {
System.out.println("pudding:"+5); return COST+drink.cost(); } } //测试类 public class Test {
public static void main(String[] args) {
Drink milk = new Milk(); milk = new Pudding(milk); milk = new Chocolate(milk); System.out.println(milk.cost()); } }
得到测试结果
chocolate:4 pudding:5 milk: 12 21.0
可以看到非常简单的就能够完成具体构件和具体装饰的组合。也可以看到结构也非常简洁明,具体构件在自己的package中,具体装饰也在自己的package中。我们不管是想要增加具体构件还是具体配饰,都可以在各自的package中添加。对已有的代码不需要进行任何操作,就算新加的有bug也不会影响原有代码的操作。
6、观察者模式:对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
观察者模式有点:
1、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
2、目标与观察者之间建立了一套触发机制。
//定义观察者接口 public interface Observer {
void response(); } //具体化观察者1 public class Observer1 implements Observer{
@Override public void response() {
System.out.println("Observer1 action"); } } //具体化观察者2 public class Observer2 implements Observer{
@Override public void response() {
System.out.println("Observer2 action"); } } //抽象目标 public abstract class Subject {
//创建观察者集合 protected ArrayList<Observer> array = new ArrayList<Observer>(); //增加观察者 public void add(Observer observer){
array.add(observer); } //删除观察者 public void remove(Observer observer){
array.remove(observer); } //通知观察者方法 public abstract void notifyObserver(); } //具体化目标 public class Subject1 extends Subject{
@Override public void notifyObserver() {
for (Observer observer :array){
observer.response(); } } } //测试类 public class Test {
public static void main(String[] args) {
Subject subject = new Subject1(); Observer obs1 = new Observer1(); Observer obs2 = new Observer2(); subject.add(obs1); subject.add(obs2); subject.notifyObserver(); } }
得到测试结果:
Observer1 action Observer2 action
//抽象处理者 public abstract class Handler {
private Handler next; public void setNext(Handler next) {
this.next = next; } public Handler getNext() {
return next; } //处理请求 public abstract void handleRequest(int info); } //具体处理者1 public class Handler1 extends Handler{
@Override public void handleRequest(int info) {
if (info <10){
System.out.println("Handler1完成处理"); }else {
if (getNext()!=null){
getNext().handleRequest(info); }else {
System.out.println("没有处理者进行处理"); } } } } //具体处理者2 public class Handler2 extends Handler{
@Override public void handleRequest(int info) {
if (info <20&&info>10){
System.out.println("Handler2完成处理"); }else {
if (getNext()!=null){
getNext().handleRequest(info); }else {
System.out.println("没有处理者进行处理"); } } } } 测试类 public class Test {
public static void main(String[] args) {
Handler handler1 = new Handler1(); Handler handler2 = new Handler2(); handler1.setNext(handler2); handler1.handleRequest(5); handler1.handleRequest(15); handler1.handleRequest(25); } }
得到测试结果:
转自:https://blog.csdn.net/a/article/details/
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/118745.html


